openapi: 3.1.0
info:
  title: NETRA LLM Gateway API
  description: |
    **NETRA** (*Sanskrit: नेत्र — Vision / Aperture / Insight*) is a high-throughput, ultra-low latency
    intelligent LLM Gateway and tenant-isolated Semantic Vector Cache.
    
    ### Core Capabilities
    - **OpenAI-Compatible Ingress**: Direct drop-in proxy at `/v1/chat/completions`.
    - **Telemetry Contract**: Every response strictly carries canonical `x-netra-*` headers.
    - **Micro-USD Precision**: Exact 6-decimal cost calculation and quota accounting.
    - **High-Throughput Streaming**: Non-blocking SSE pass-through over Java 25 Virtual Threads.
    - **Atomic Redis 8.0 Admission**: Sliding-window rate limiting & zero over-admission budget accounting.
    - **Semantic Vector Cache**: Two-tier cache hierarchy (Tier 1 SHA-256 exact hash in <0.5ms + Tier 2 pgvector HNSW in <5ms).
    - **Resilience & Failover**: Resilience4j circuit breakers (<0.05ms fast-failover) and small-model refusal auto-escalation.
    - **React 19 / Vite 6 Ops Console**: Real-time OpenRouter-grade analytics, prompt playground, and virtual keys management.
  version: 0.7.0
  contact:
    name: Shashank Chandel
    email: shashankchandel@gmail.com
    url: https://github.com/shashankch/netra-llmgateway
  license:
    name: Apache-2.0
    url: https://github.com/shashankch/netra-llmgateway/blob/main/LICENSE

servers:
  - url: http://localhost:8080
    description: Local Gateway (Docker & Development)
  - url: https://gateway-netrallm.avadhanlabs.dev
    description: Production Gateway Data Plane
  - url: https://docs-netrallm.avadhanlabs.dev
    description: Production Documentation Site & Schema Reference

security:
  - BearerAuth: []

paths:
  /v1/chat/completions:
    post:
      summary: Create Chat Completion
      description: |
        Processes chat completion requests with virtual key authentication, model allowlist enforcement,
        semantic vector cache lookup, dynamic failover, and micro-USD telemetry header injection.
      operationId: createChatCompletion
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
            example:
              model: "fast"
              messages:
                - role: "user"
                  content: "What is an event-driven architecture?"
              temperature: 0.7
              max_tokens: 150
              stream: false
      responses:
        '200':
          description: Successful chat completion or streaming SSE event pump.
          headers:
            x-netra-provider:
              description: Upstream provider and concrete model that served the request (e.g. `alpha/alpha-small`).
              schema:
                type: string
                example: "alpha/alpha-small"
            x-netra-cache:
              description: Semantic vector cache lookup status (`hit` or `miss`).
              schema:
                type: string
                enum: [hit, miss]
                example: "miss"
            x-netra-fallback:
              description: Indicates whether secondary fallback model was invoked due to primary upstream failure.
              schema:
                type: string
                enum: ["true", "false"]
                example: "false"
            x-netra-cost-usd:
              description: Exact cost in USD calculated with 6 decimal places ($0.000000). Omitted on streaming requests until reconciled.
              schema:
                type: string
                example: "0.000015"
            x-netra-route-reason:
              description: Routing policy reasoning (e.g. `alias_direct`, `auto:complexity_simple`, `fallback_retry`).
              schema:
                type: string
                example: "alias_direct"
            x-netra-retries:
              description: Number of upstream network retries executed.
              schema:
                type: integer
                example: 0
            x-netra-cache-tier:
              description: Cache tier that fulfilled the query (`tier1_exact` or `tier2_semantic`).
              schema:
                type: string
                enum: [tier1_exact, tier2_semantic]
                example: "tier1_exact"
            x-netra-escalated:
              description: Indicates whether a small-model refusal was automatically escalated to the smart reasoning tier.
              schema:
                type: string
                enum: ["true", "false"]
                example: "true"
            RateLimit-Limit:
              description: Maximum request quota configured for the active sliding window.
              schema:
                type: integer
                example: 60
            RateLimit-Remaining:
              description: Remaining requests permitted within the current window.
              schema:
                type: integer
                example: 57
            RateLimit-Reset:
              description: Relative delta in seconds until the active rate limit window resets.
              schema:
                type: integer
                example: 42
            RateLimit-Policy:
              description: Quota policy definition conforming to IETF draft (`<limit>;w=<window_seconds>`).
              schema:
                type: string
                example: "60;w=60"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
            text/event-stream:
              schema:
                type: string
                description: Real-time Server-Sent Events (SSE) data stream ending with `data: [DONE]`.
        '400':
          description: Invalid request payload, malformed JSON, or empty messages array.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing, invalid, or deactivated virtual API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Monthly budget cap exhausted for this virtual key (`budget_exceeded`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Model not permitted for this tenant (`model_not_allowed`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Requested model alias or concrete model not found in catalog.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded (sliding-window RPM exhaustion).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: Upstream foundation model provider failure or network timeout.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal gateway unexpected error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/usage:
    get:
      summary: Usage Summary & Reconciliation API
      description: |
        Returns aggregated spend and token usage for a virtual key over a date window.
        Guarantees exact reconciliation with client-side load test totals.
      operationId: getUsageSummary
      security:
        - AdminBearerAuth: []
      parameters:
        - name: key
          in: query
          required: false
          description: Virtual key to filter usage for. Defaults to all tenants if omitted.
          schema:
            type: string
            example: "netra-sk-search-1a2b3c"
        - name: from
          in: query
          required: false
          description: Start date (YYYY-MM-DD format). Defaults to beginning of current month.
          schema:
            type: string
            example: "2026-10-01"
        - name: to
          in: query
          required: false
          description: End date (YYYY-MM-DD format). Defaults to current date.
          schema:
            type: string
            example: "2026-10-24"
      responses:
        '200':
          description: Aggregated token counts, spend in USD, and cache hits.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageSummaryResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/logs:
    get:
      summary: Audit & Request Logs API
      description: |
        Returns chronological request log entries, newest first, filterable by virtual key.
        Includes all rejections (401, 403, 404, 429, 402, 502) and successful calls.
      operationId: getRequestLogs
      security:
        - AdminBearerAuth: []
      parameters:
        - name: key
          in: query
          required: false
          description: Optional virtual key filter.
          schema:
            type: string
            example: "netra-sk-search-1a2b3c"
        - name: status
          in: query
          required: false
          description: Optional status code (e.g. 200, 429, 401, 502) or error filter (ERR).
          schema:
            type: string
            example: "429"
        - name: search
          in: query
          required: false
          description: Case-insensitive search query across request ID, model, key, and route reason.
          schema:
            type: string
            example: "smart"
        - name: limit
          in: query
          required: false
          description: Maximum number of recent log entries to return (default 50, max 500).
          schema:
            type: integer
            default: 50
            example: 20
        - name: page
          in: query
          required: false
          description: Zero-indexed page number for pagination.
          schema:
            type: integer
            default: 0
            example: 0
        - name: offset
          in: query
          required: false
          description: Zero-indexed record offset for cursor/offset pagination.
          schema:
            type: integer
            example: 25
      responses:
        '200':
          description: Array of request log entries.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RequestLogEntry'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/cache/stats:
    get:
      summary: Semantic Vector Cache Statistics
      description: Returns aggregate cache hit rates, entry counts, and per-tenant cryptographic isolation breakdowns.
      operationId: getCacheStats
      security:
        - AdminBearerAuth: []
      responses:
        '200':
          description: Aggregate cache statistics and per-key breakdown.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CacheStatsResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/cache/entries:
    get:
      summary: Inspect Cached Content Entries
      description: Returns detailed cached prompt/response entries, filterable by virtual key and search text.
      operationId: getCacheEntries
      security:
        - AdminBearerAuth: []
      parameters:
        - name: key
          in: query
          required: false
          schema:
            type: string
          description: Tenant virtual key namespace to filter entries.
        - name: search
          in: query
          required: false
          schema:
            type: string
          description: Substring match on prompt text or model alias.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 50
        - name: page
          in: query
          required: false
          schema:
            type: integer
            default: 0
        - name: offset
          in: query
          required: false
          schema:
            type: integer
          description: Zero-based cursor offset.
      responses:
        '200':
          description: List of cached prompt completion records.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CacheEntryDetail'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/cache/entries/{id}:
    delete:
      summary: Purge Specific Cache Entry
      description: Evicts a cached completion entry from both vector database and in-memory caches.
      operationId: deleteCacheEntry
      security:
        - AdminBearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Cache entry eviction confirmation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  id:
                    type: string
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/keys:
    get:
      summary: List Virtual API Keys
      description: Returns all provisioned virtual keys with live RPM quotas, monthly budget caps, spend, and status.
      operationId: listVirtualKeys
      security:
        - AdminBearerAuth: []
      responses:
        '200':
          description: List of all provisioned virtual keys.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TenantAdminResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Provision Virtual API Key
      description: Creates a new virtual API key with sliding RPM limit, budget cap, model allowlist, and similarity threshold.
      operationId: createVirtualKey
      security:
        - AdminBearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTenantRequest'
      responses:
        '201':
          description: Virtual key successfully provisioned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantAdminResponse'
        '400':
          description: Invalid request parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/keys/{id}:
    put:
      summary: Update Virtual API Key
      description: Updates virtual key rate limits, budget caps, allowlists, or active status.
      operationId: updateVirtualKey
      security:
        - AdminBearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTenantRequest'
      responses:
        '200':
          description: Virtual key updated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantAdminResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: Revoke Virtual API Key
      description: Deactivates virtual API key; subsequent requests return HTTP 401.
      operationId: revokeVirtualKey
      security:
        - AdminBearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '204':
          description: Virtual key revoked successfully.
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/logs/stream-ticket:
    post:
      summary: Issue SSE Stream Ticket
      description: Issues a short-lived (60s) single-use ticket for secure EventSource SSE log streaming without exposing admin credentials in query parameters.
      operationId: issueStreamTicket
      security:
        - AdminBearerAuth: []
      responses:
        '200':
          description: Ephemeral stream ticket.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StreamTicketResponse'
        '401':
          description: Unauthorized admin token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /admin/logs/stream:
    get:
      summary: Live SSE Request Logs Stream
      description: Real-time Server-Sent Events stream of incoming request audit logs and rejections.
      operationId: streamRequestLogs
      security:
        - AdminBearerAuth: []
      parameters:
        - name: ticket
          in: query
          required: false
          description: Ephemeral single-use stream ticket issued by POST /admin/logs/stream-ticket.
          schema:
            type: string
            example: "stk-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        - name: token
          in: query
          required: false
          deprecated: true
          description: Deprecated admin secret query parameter. Use ticket or Authorization header instead.
          schema:
            type: string
            example: "netra-admin-demo"
      responses:
        '200':
          description: SSE stream of incoming audit logs.
          content:
            text/event-stream:
              schema:
                type: string

  /admin/currency/rate:
    get:
      summary: Live Forex Rate
      description: Returns active USD to INR exchange rate with dynamic fallback.
      operationId: getCurrencyRate
      security: []
      responses:
        '200':
          description: Current exchange rate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrencyRateResponse'

  /admin/pricing:
    get:
      summary: Model Pricing Catalog & Aliases
      description: Returns configured model aliases, active pricing rates per 1M tokens, fallback chains, and foundation model catalogs.
      operationId: getPricingCatalog
      security:
        - AdminBearerAuth: []
      responses:
        '200':
          description: Model pricing and alias configurations.
          content:
            application/json:
              schema:
                type: object
                properties:
                  aliases:
                    type: object
                  models:
                    type: array
                    items:
                      type: object
        '401':
          $ref: '#/components/responses/401Unauthorized'

  /admin/providers/health:
    get:
      summary: Upstream Provider Health & Circuit Breakers
      description: Returns live health snapshots, circuit breaker states, rolling error rates, and p95 latencies per provider.
      operationId: getProviderHealth
      security:
        - AdminBearerAuth: []
      responses:
        '200':
          description: Provider health snapshots.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ProviderHealthSnapshot'
        '401':
          $ref: '#/components/responses/401Unauthorized'

  /health:
    get:
      summary: Service Ping Probe
      description: Returns gateway operating status, service identity, and release version.
      operationId: getHealth
      security: []
      responses:
        '200':
          description: Gateway is healthy and accepting traffic.
          content:
            application/json:
              schema:
                type: object
                required:
                  - status
                  - service
                  - version
                properties:
                  status:
                    type: string
                    example: "ok"
                  service:
                    type: string
                    example: "netra-gateway"
                  version:
                    type: string
                    example: "0.7.0"

  /health/live:
    get:
      summary: Container Liveness Probe
      description: Basic liveness check for Kubernetes and container orchestrators.
      operationId: getHealthLive
      security: []
      responses:
        '200':
          description: Process is alive.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
                  service:
                    type: string
                    example: "netra-gateway"
                  version:
                    type: string
                    example: "0.7.0"

  /health/ready:
    get:
      summary: Deep Synthetic Readiness Probe
      description: Verifies active connections to PostgreSQL and Redis cluster before admitting traffic.
      operationId: getHealthReady
      security: []
      responses:
        '200':
          description: Gateway and backing dependencies are fully healthy.
          content:
            application/json:
              schema:
                type: object
                required:
                  - status
                  - database
                  - redis
                  - seeder
                  - version
                properties:
                  status:
                    type: string
                    example: "UP"
                  database:
                    type: string
                    example: "UP"
                  redis:
                    type: string
                    example: "UP"
                  seeder:
                    type: string
                    enum: [READY, SEEDING]
                    example: "READY"
                  version:
                    type: string
                    example: "0.7.0"
        '503':
          description: Backing database or Redis is unavailable.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "DEGRADED"
                  database:
                    type: string
                    example: "DOWN"
                  redis:
                    type: string
                    example: "UP"
                  version:
                    type: string
                    example: "0.7.0"

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Virtual Key (`netra-sk-*`)
      description: Provide tenant virtual API key in the `Authorization: Bearer <key>` header.
    AdminBearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Admin Token
      description: Provide platform admin secret in the `Authorization: Bearer <admin-token>` header.

  responses:
    401Unauthorized:
      description: Unauthorized admin token or missing virtual key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  schemas:
    ChatMessage:
      type: object
      required:
        - role
        - content
      properties:
        role:
          type: string
          enum: [system, user, assistant, function]
          example: "user"
        content:
          type: string
          example: "Explain CAP theorem in one sentence."

    ChatCompletionRequest:
      type: object
      required:
        - model
        - messages
      properties:
        model:
          type: string
          description: Target model alias (`fast`, `smart`, `auto`) or concrete provider model (`alpha-small`, `beta-large`).
          example: "fast"
        messages:
          type: array
          items:
            $ref: '#/components/schemas/ChatMessage'
        stream:
          type: boolean
          default: false
          description: If true, emits streaming Server-Sent Events (SSE).
        temperature:
          type: number
          format: float
          default: 1.0
          minimum: 0.0
          maximum: 2.0
        max_tokens:
          type: integer
          minimum: 1
          description: Maximum number of tokens to generate.

    UsageInfo:
      type: object
      required:
        - prompt_tokens
        - completion_tokens
        - total_tokens
      properties:
        prompt_tokens:
          type: integer
          example: 12
        completion_tokens:
          type: integer
          example: 48
        total_tokens:
          type: integer
          example: 60

    Choice:
      type: object
      required:
        - index
        - message
        - finish_reason
      properties:
        index:
          type: integer
          example: 0
        message:
          $ref: '#/components/schemas/ChatMessage'
        finish_reason:
          type: string
          enum: [stop, length, content_filter, tool_calls]
          example: "stop"

    ChatCompletionResponse:
      type: object
      required:
        - id
        - object
        - created
        - model
        - choices
        - usage
      properties:
        id:
          type: string
          example: "chatcmpl-9x1a2b3c4d5e"
        object:
          type: string
          example: "chat.completion"
        created:
          type: integer
          format: int64
          example: 1729732000
        model:
          type: string
          example: "alpha-small"
        choices:
          type: array
          items:
            $ref: '#/components/schemas/Choice'
        usage:
          $ref: '#/components/schemas/UsageInfo'

    ErrorDetail:
      type: object
      required:
        - message
        - type
        - code
      properties:
        message:
          type: string
          example: "Virtual API key is deactivated"
        type:
          type: string
          example: "authentication_error"
        code:
          type: string
          example: "invalid_api_key"

    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'

    UsageSummaryResponse:
      type: object
      required:
        - key
        - from
        - to
        - requests
        - prompt_tokens
        - completion_tokens
        - cost_usd
        - cache_hits
      properties:
        key:
          type: string
          example: "netra-sk-search-1a2b3c"
        from:
          type: string
          example: "2026-10-01"
        to:
          type: string
          example: "2026-10-24"
        requests:
          type: integer
          example: 412
        prompt_tokens:
          type: integer
          example: 18734
        completion_tokens:
          type: integer
          example: 9211
        cost_usd:
          type: number
          format: double
          example: 0.014100
        cache_hits:
          type: integer
          example: 96

    RequestLogEntry:
      type: object
      required:
        - id
        - request_id
        - virtual_key
        - requested_model
        - status
        - status_code
        - prompt_tokens
        - completion_tokens
        - cost_usd
        - cache
        - fallback
        - retries
        - latency_ms
        - is_stream
        - created_at
      properties:
        id:
          type: string
          format: uuid
        request_id:
          type: string
          example: "req_1a2b3c4d5e6f"
        virtual_key:
          type: string
          example: "netra-sk-search-1a2b3c"
        requested_model:
          type: string
          example: "fast"
        resolved_provider:
          type: string
          nullable: true
          example: "alpha"
        resolved_model:
          type: string
          nullable: true
          example: "alpha-small"
        status:
          type: string
          example: "ok"
        status_code:
          type: integer
          example: 200
        prompt_tokens:
          type: integer
          example: 12
        completion_tokens:
          type: integer
          example: 48
        cost_usd:
          type: number
          format: double
          example: 0.000015
        cache:
          type: string
          example: "miss"
        fallback:
          type: boolean
          example: false
        route_reason:
          type: string
          nullable: true
          example: "alias_direct"
        retries:
          type: integer
          example: 0
        latency_ms:
          type: integer
          example: 32
        is_stream:
          type: boolean
          example: false
        error_type:
          type: string
          nullable: true
          example: null
        created_at:
          type: string
          format: date-time
          example: "2026-10-24T15:00:00Z"

    CacheStatsResponse:
      type: object
      required:
        - total_entries
        - total_hits
        - total_misses
        - hit_rate
        - keys
      properties:
        total_entries:
          type: integer
          example: 150
        total_hits:
          type: integer
          example: 120
        total_misses:
          type: integer
          example: 30
        hit_rate:
          type: number
          format: double
          example: 0.80
        tier1_exact_hits:
          type: integer
          example: 45
        tier2_semantic_hits:
          type: integer
          example: 75
        keys:
          type: object
          additionalProperties:
            type: object
            required:
              - entries
              - hits
              - misses
              - hit_rate
            properties:
              entries:
                type: integer
                example: 150
              hits:
                type: integer
                example: 120
              misses:
                type: integer
                example: 30
              hit_rate:
                type: number
                format: double
                example: 0.80
              tier1_exact_hits:
                type: integer
                example: 45
              tier2_semantic_hits:
                type: integer
                example: 75
              similarity_threshold:
                type: number
                format: double
                example: 0.920
              cache_enabled:
                type: boolean
                example: true

    CacheEntryDetail:
      type: object
      required:
        - id
        - virtual_key
        - model_alias
        - prompt_text
        - response_json
        - hit_count
      properties:
        id:
          type: string
          format: uuid
        virtual_key:
          type: string
          example: netra-sk-search-1a2b3c
        model_alias:
          type: string
          example: fast
        prompt_text:
          type: string
          example: Explain what load balancers do in distributed web systems.
        resolved_provider:
          type: string
          example: openrouter/openai/gpt-4o-mini
        completion_text:
          type: string
          example: Load balancers distribute incoming network traffic across a farm of backend servers.
        response_json:
          type: string
          description: Full serialized OpenAI-compatible ChatCompletionResponse JSON
        hit_count:
          type: integer
          example: 18
        created_at:
          type: string
          format: date-time
        last_hit_at:
          type: string
          format: date-time
        similarity_threshold:
          type: number
          format: double
          example: 0.920
        tier:
          type: string
          enum: [tier1_exact, tier2_semantic]
          example: tier2_semantic

    TenantAdminResponse:
      type: object
      required:
        - id
        - virtual_key
        - team
        - monthly_budget_usd
        - current_spend_usd
        - rpm_limit
        - model_allowlist
        - semantic_cache_enabled
        - similarity_threshold
        - is_active
        - status
      properties:
        id:
          type: string
          format: uuid
        virtual_key:
          type: string
          example: "netra-sk-search-1a2b3c"
        team:
          type: string
          example: "Search Team"
        monthly_budget_usd:
          type: number
          format: double
          example: 100.0
        current_spend_usd:
          type: number
          format: double
          example: 14.25
        rpm_limit:
          type: integer
          example: 60
        tpm_limit:
          type: integer
          nullable: true
          example: 100000
        model_allowlist:
          type: array
          items:
            type: string
          example: ["fast", "smart", "auto"]
        semantic_cache_enabled:
          type: boolean
          example: true
        similarity_threshold:
          type: number
          format: double
          example: 0.92
        is_active:
          type: boolean
          example: true
        status:
          type: string
          enum: [ACTIVE, EXHAUSTED, REVOKED]
          example: "ACTIVE"
        created_at:
          type: string
          format: date-time

    CreateTenantRequest:
      type: object
      required:
        - team
      properties:
        virtual_key:
          type: string
          nullable: true
          example: "netra-sk-custom-key"
        team:
          type: string
          example: "Search Core"
        monthly_budget_usd:
          type: number
          format: double
          example: 100.0
        rpm_limit:
          type: integer
          example: 60
        tpm_limit:
          type: integer
          example: 100000
        model_allowlist:
          type: array
          items:
            type: string
          example: ["fast", "smart", "auto"]
        semantic_cache_enabled:
          type: boolean
          example: true
        similarity_threshold:
          type: number
          format: double
          example: 0.85

    UpdateTenantRequest:
      type: object
      properties:
        team:
          type: string
          example: "Search Core"
        monthly_budget_usd:
          type: number
          format: double
          example: 250.0
        rpm_limit:
          type: integer
          example: 120
        tpm_limit:
          type: integer
          example: 200000
        model_allowlist:
          type: array
          items:
            type: string
        semantic_cache_enabled:
          type: boolean
        similarity_threshold:
          type: number
          format: double
        is_active:
          type: boolean

    CurrencyRateResponse:
      type: object
      required:
        - base
        - target
        - rate
      properties:
        base:
          type: string
          example: "USD"
        target:
          type: string
          example: "INR"
        rate:
          type: number
          format: double
          example: 85.00

    ProviderHealthSnapshot:
      type: object
      required:
        - provider
        - status
        - circuit_state
        - failure_rate
        - slow_call_rate
      properties:
        provider:
          type: string
          example: "alpha"
        status:
          type: string
          enum: [HEALTHY, DEGRADED, DOWN]
          example: "HEALTHY"
        circuit_state:
          type: string
          enum: [CLOSED, OPEN, HALF_OPEN]
          example: "CLOSED"
        failure_rate:
          type: number
          format: float
          example: 0.0
        slow_call_rate:
          type: number
          format: float
          example: 0.0
        buffered_calls:
          type: integer
          example: 20
        successful_calls:
          type: integer
          example: 20
        failed_calls:
          type: integer
          example: 0
        slow_calls:
          type: integer
          example: 0
        p95_latency_ms:
          type:
            - integer
            - "null"
          nullable: true
          description: Rolling p95 latency in milliseconds, or null if no latency samples have been recorded yet.
          example: 24

    StreamTicketResponse:
      type: object
      required:
        - ticket
        - expires_in
      properties:
        ticket:
          type: string
          example: "stk-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        expires_in:
          type: integer
          example: 60

