openapi: "3.0.3"
info:
  title: KWJ Agent Infrastructure API
  description: |
    Token-saving infrastructure tools for AI agents. 50 tools that intercept wasteful
    Claude operations — caching, compression, slicing, search — reducing context size by
    80-98% on every operation they handle.

    ## Authentication
    Pass your API key as a query parameter: `?api_key=kwj_your_key_here`

    ## Getting an API key
    POST https://kwj.ai/buy with `email=you@example.com` — free 1-hour trial key issued
    instantly. Upgrade to $19/month for unlimited use.

    ## Token savings per tool
    - web_read: eliminates redundant web fetches (100% on cache hit, 3600s TTL)
    - digest: 500-line log -> 30 lines (94% reduction), errors always preserved
    - cache_get: fuzzy Jaccard answer lookup (never recompute same analysis)
    - doc_extract: PDF/XLSX/CSV without loading full doc into context
  version: "1.0.0"
  contact:
    email: hello@kwj.ai
  license:
    name: Proprietary

servers:
  - url: https://kwj.ai
    description: Production

paths:
  /api/v1/web_read:
    get:
      operationId: web_read
      summary: Fetch a web page (cached, TTL 3600s)
      x-kwj-savings-percent: 100
      description: |
        Fetches a URL and returns the text content. Results are cached by URL hash with
        a 3600-second TTL. On cache hit, zero network cost. Use instead of raw HTTP fetches
        to eliminate redundant web reads across agent turns.
      parameters:
        - name: url
          in: query
          required: true
          description: The URL to fetch
          schema:
            type: string
            example: "https://docs.anthropic.com/en/api/getting-started"
        - name: api_key
          in: query
          required: true
          description: Your KWJ API key (kwj_...)
          schema:
            type: string
      responses:
        "200":
          description: Page text content
          content:
            text/plain:
              schema:
                type: string
              examples:
                cached:
                  summary: Cache hit response
                  value:
                    ok: true
                    cached: true
                    content: "...page content..."
                    tokens_approx: 0
                miss:
                  summary: Cache miss
                  value:
                    ok: true
                    cached: false
                    content: "...fetched page content..."
                    tokens_approx: 1200
        "400":
          description: Missing url parameter
        "401":
          description: Invalid or expired api_key
        "429":
          description: Trial limit reached (100 calls/day)

  /api/v1/digest:
    get:
      operationId: digest
      summary: Compress noisy command/log output (94% reduction)
      x-kwj-savings-percent: 94
      description: |
        Shrinks noisy log, command, or file output before it enters Claude context.
        Collapses repeated lines, elides middles, always rescues error/warning/fail/panic lines.
        Typical: 500-line build log -> 30 essential lines. Pass raw command output as `input`.
      parameters:
        - name: input
          in: query
          required: true
          description: Raw text to compress (log output, command result, etc.)
          schema:
            type: string
        - name: api_key
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Compressed text with errors/warnings preserved
          content:
            text/plain:
              schema:
                type: string
              examples:
                build_log:
                  summary: Compressed build log
                  value: |
                    [digested 487 lines -> 13 lines]
                    error[E0382]: borrow of moved value: `x`
                       --> src/main.rs:42:5
                    warning: unused variable `y` (3 occurrences suppressed)
                    [build FAILED]
        "400":
          description: Missing input parameter
        "401":
          description: Invalid or expired api_key

  /api/v1/cache_get:
    get:
      operationId: cache_get
      summary: Fuzzy answer cache lookup (Jaccard similarity)
      x-kwj-savings-percent: 100
      description: |
        Looks up a previously stored analysis result by fuzzy query match.
        Uses Jaccard shingle similarity at 0.35 threshold — near-identical queries
        hit the cache even if phrased differently. Returns hit=true and the stored
        value on match, hit=false on miss. Use before any expensive analysis.
      parameters:
        - name: q
          in: query
          required: true
          description: The query to look up
          schema:
            type: string
            example: "security audit findings for Uniswap v3 TWAP oracle"
        - name: api_key
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Cache lookup result
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  hit:
                    type: boolean
                    description: true if a cached answer was found
                  value:
                    type: string
                    nullable: true
                    description: The cached answer, or null on miss
              examples:
                hit:
                  summary: Cache hit
                  value:
                    ok: true
                    hit: true
                    value: "Uniswap v3 TWAP oracle is vulnerable to price manipulation in low-liquidity pools..."
                miss:
                  summary: Cache miss
                  value:
                    ok: true
                    hit: false
                    value: null

  /api/v1/doc_extract:
    get:
      operationId: doc_extract
      summary: Extract text from PDF, XLSX, or CSV without full-load
      x-kwj-savings-percent: 95
      description: |
        Parses a document file and returns extracted text content. Supports PDF
        (3-tier: native text layer, rasterized OCR, pure-Rust fallback), XLSX,
        and CSV. Returns plain text or structured JSON with per-page confidence.
        Eliminates loading entire documents into context.
      parameters:
        - name: file
          in: query
          required: true
          description: Absolute path to the document file on the server
          schema:
            type: string
            example: "/tmp/report.pdf"
        - name: api_key
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Extracted text content
          content:
            text/plain:
              schema:
                type: string
              examples:
                pdf_extract:
                  summary: PDF text extraction
                  value: |
                    Page 1:
                    KWJ Infrastructure Report Q2 2026
                    Token savings achieved: 90.3% reduction...
                    [confidence: 0.97]
        "400":
          description: Missing file parameter
        "401":
          description: Invalid or expired api_key

  /health:
    get:
      operationId: health_check
      summary: Service health check
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: "OK"

  /buy:
    post:
      operationId: request_trial_key
      summary: Request a free trial API key
      description: |
        Submit an email address to receive a free 1-hour trial API key.
        Trial includes 100 API calls per day. Upgrade to $19/month for unlimited use.
        One trial per email address. Disposable email domains are blocked.
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                  example: "you@company.com"
                name:
                  type: string
                  example: "Jane Smith"
      responses:
        "200":
          description: HTML confirmation page with setup instructions
