# Proposed contract, version 1: endpoints, errors, paging, idempotency, security and the capability of every
# operation. Resource schemas were initialized from the data model (docs/06-data) and are kept aligned with it; input
# schemas (*Input, *Request) and views are specific to this contract. Status: proposal for review, not confirmed design.
# Conventions: docs/05-interfaces/choosing-an-interface.md. Vendor extensions: x-moonitoring-audience (who calls),
# x-moonitoring-capability (the capability checked), x-moonitoring-entitlement (the entitlement feature checked),
# x-moonitoring-requirements (the requirements of 1.requisiti-raffinati.txt the operation serves).
openapi: 3.1.0
info:
  title: AI Gateway Completions API
  version: 1.0.0
  description: 'Every call to a language model goes through `ai-gateway`: it holds the provider keys, routes each
    request by data class and plan tier, checks prompts with Model Armor, reserves and settles the Organization''s
    usage and keeps a ledger of every call without the prompt. Systems call it through the gRPC service of this
    domain; this REST API is the staff view of the ledger and the providers.'
servers:
- url: https://ai-gateway.moonitoring.com/completions/v1
  description: Prod
- url: https://stage-ai-gateway.moonitoring.com/completions/v1
  description: Stage, through IAP
security:
- bearer: []
tags:
- name: Ledger
  description: One row per model call
- name: Providers
  description: Where calls go
paths:
  /model-calls:
    get:
      summary: List model calls
      operationId: listModelCalls
      tags:
      - Ledger
      parameters:
      - name: organization
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this Organization.
      - name: feature
        in: query
        required: false
        schema:
          type: string
        description: Only this feature.
      - name: model
        in: query
        required: false
        schema:
          type: string
      - name: outcome
        in: query
        required: false
        schema:
          type: string
          enum:
          - ok
          - blocked_by_model_armor
          - blocked_by_data_class
          - not_entitled
          - limit_reached
          - provider_error
          - timeout
        description: Only this outcome.
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Occurred at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Occurred before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ModelCall'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-gateway.usage.read
      x-moonitoring-requirements:
      - '69'
      - '121.9'
      - '121.10'
      - '125.9'
  /model-calls/{call_id}:
    get:
      summary: Read a model call
      operationId: getModelCall
      tags:
      - Ledger
      parameters:
      - name: call_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelCall'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-gateway.usage.read
      x-moonitoring-requirements:
      - '69'
  /providers:
    get:
      summary: List providers
      operationId: listProviders
      tags:
      - Providers
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Provider'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-gateway.usage.read
      x-moonitoring-requirements:
      - '121.3'
      - '121.5'
      - '121.6'
components:
  schemas:
    ModelCall:
      type: object
      description: 'One model call, as the ledger keeps it: who, which model, how many tokens, cost and latency.
        Never the prompt or the answer.'
      properties:
        id:
          type: string
          format: uuid
        request_id:
          type: string
          description: The same id as in Cloud Logging and in AgentMessage.request_id.
        organization:
          type: string
          format: uuid
        moonitoring_user:
          type: string
          format: uuid
        user:
          type: string
          format: uuid
        feature:
          type: string
          description: The metered feature, e.g. moochat.chat.
        caller:
          type: string
          description: The system that called, e.g. moochat, grant.
        provider:
          type: string
          enum:
          - vertex_ai
          - openrouter
        model:
          type: string
        model_profile:
          type: string
          format: uuid
        data_class:
          type: string
          enum:
          - public
          - personal
        input_tokens:
          type: integer
        output_tokens:
          type: integer
        cost_micros:
          type: integer
        latency_ms:
          type: integer
        outcome:
          type: string
          enum:
          - ok
          - blocked_by_model_armor
          - blocked_by_data_class
          - not_entitled
          - limit_reached
          - provider_error
          - timeout
        occurred_at:
          type: string
          format: date-time
      required:
      - id
      - request_id
      - feature
      - caller
      - provider
      - model
      - data_class
      - outcome
      - occurred_at
    Provider:
      type: object
      description: A model provider as the gateway sees it. Keys never appear.
      properties:
        name:
          type: string
          enum:
          - vertex_ai
          - openrouter
        data_classes:
          type: array
          items:
            type: string
            enum:
            - public
            - personal
        region:
          type: string
        status:
          type: string
          enum:
          - healthy
          - degraded
          - down
        key_rotated_at:
          type: string
          format: date-time
        credit_limit_micros:
          type: integer
          description: 'OpenRouter: the per-environment key credit limit, a backstop.'
        credit_used_micros:
          type: integer
      required:
      - name
      - data_classes
      - status
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The short-lived token signed by `access`: an Organization user token, a staff token or a client
        token, as the operation''s audience says.'
