openapi: 3.1.0
info:
  title: HideMyPaper API
  version: "0.1.0"
  description: >
    Humanize AI text and estimate how AI-like text is. Authenticate developer
    endpoints with an API key (X-API-Key). Humanizing also requires your own
    OpenRouter key per request (X-OpenRouter-Key) — it is never stored.
    The AI-likeness score is a free heuristic estimate, not a commercial-grade detector.
servers:
  - url: https://hidemypaper.app
security:
  - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string }
            message: { type: string }
            request_id: { type: string }
    DiffOp:
      type: object
      properties:
        type: { type: string, enum: [add, del, eq] }
        value: { type: string }
    HumanizeResponse:
      type: object
      properties:
        result: { type: string }
        scoreBefore: { type: number, description: "0..1 AI-likeness before (heuristic)" }
        scoreAfter: { type: number, description: "0..1 AI-likeness after (heuristic)" }
        diff:
          type: array
          items: { $ref: "#/components/schemas/DiffOp" }
        tokensUsed:
          type: object
          properties:
            input: { type: integer }
            output: { type: integer }
        stats:
          type: object
          properties:
            mode: { type: string }
            passes: { type: integer }
            unitsRewritten: { type: integer }
            unitsKeptOriginal: { type: integer }
    DetectResponse:
      type: object
      properties:
        verdict: { type: string, enum: [human, uncertain, ai] }
        aiPercentage: { type: integer }
        confidence: { type: string, enum: [low, medium, high] }
        caveat: { type: string }
        sentences:
          type: array
          items:
            type: object
            properties:
              text: { type: string }
              aiScore: { type: number }
              highlight: { type: boolean }
paths:
  /api/v1/humanize:
    post:
      summary: Humanize AI text
      description: Requires X-API-Key and your OpenRouter key in X-OpenRouter-Key (used per request, never stored).
      parameters:
        - in: header
          name: X-OpenRouter-Key
          required: true
          schema: { type: string }
          description: Your OpenRouter API key (sk-or-…).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [text]
              properties:
                text: { type: string, maxLength: 12000 }
                mode: { type: string, enum: [light, standard, deep, max], default: standard }
                model: { type: string, description: "OpenRouter model id (optional)" }
                voice: { type: string, enum: [casual, academic, journalistic, plain] }
      responses:
        "200":
          description: Humanized text + before/after score + redline diff.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/HumanizeResponse" }
        "400":
          description: Bad request or missing OpenRouter key
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
        "429":
          description: Rate limited (per API key)
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
  /api/v1/detect:
    post:
      summary: Estimate AI-likeness (authenticated)
      parameters:
        - in: query
          name: detail
          schema: { type: string, enum: [minimal, standard, full], default: standard }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [text]
              properties:
                text: { type: string, maxLength: 50000 }
                detail: { type: string, enum: [minimal, standard, full] }
      responses:
        "200":
          description: Heuristic detection result.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/DetectResponse" }
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
  /api/detect:
    post:
      summary: Estimate AI-likeness (free, no key)
      security: []
      parameters:
        - in: query
          name: detail
          schema: { type: string, enum: [minimal, standard, full], default: standard }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [text]
              properties:
                text: { type: string, maxLength: 50000 }
      responses:
        "200":
          description: Heuristic detection result.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/DetectResponse" }
