openapi: 3.1.0
info:
  title: "Asteon AI Gateway"
  version: 1.0.0
  summary: "Én gateway, 20+ AI-leverandører, full prisinnsikt og forbruksrapportering."
  description: "Asteon Gateway proxy-er kall til OpenAI, Anthropic, Google, xAI, Mistral, DeepSeek, Replicate, ElevenLabs og 12+ andre leverandører — med automatisk wallet-debet, smart-routing og enhetlig feilformat.\n\nAlle kall krever en `agw_*`-nøkkel. Generer en under [/developers](https://asteon.ai/developers)."
  contact:
    name: "Asteon Support"
    email: support@asteon.ai
    url: https://asteon.ai/help
  license:
    name: "Asteon Terms of Service"
    url: https://asteon.ai/terms
servers:
  - url: https://api.asteon.ai/api
    description: Produksjon
security:
  - bearerAuth: []
tags:
  - name: Gateway
    description: "Proxy mot AI-leverandører — samme path og JSON-schema som leverandørens eget API."
  - name: Smart-routing
    description: "Be om en modell-klasse og la Asteon velge billigste tilgjengelige leverandør."
  - name: Spend
    description: "Forbruks- og kostnadsrapportering per prosjekt og leverandør."
  - name: Providers
    description: "Offentlig pris-katalog over alle leverandører Asteon støtter."
paths:
  "/external/{provider}/{path}":
    post:
      tags:
        - Gateway
      summary: "Proxy-kall til en spesifikk leverandør"
      description: "Sender request-en videre til den valgte leverandøren med samme JSON-schema som leverandørens eget API. Wallet-en debiteres når svaret er mottatt og kostnaden er beregnet.\n\nEksempel: `POST /external/openai/v1/chat/completions` oppfører seg identisk med OpenAI sitt eget endepunkt — bare bytt ut base-URL og nøkkel."
      parameters:
        - name: provider
          in: path
          required: true
          description: "Leverandør-ID (`openai`, `anthropic`, `google`, `xai`, `mistral`, `deepseek`, `groq`, `moonshot`, `openrouter`, `replicate`, `elevenlabs`, `suno`, `leonardo`, `meshy`, `tripo`, `blockade-labs`, `eden-ai`, `firecrawl`, `pixabay`, `huggingface`, `freesound`)."
          schema:
            type: string
            example: openai
        - name: path
          in: path
          required: true
          description: "Leverandør-spesifikk sti (f.eks. `v1/chat/completions`)."
          schema:
            type: string
            example: v1/chat/completions
        - "$ref": "#/components/parameters/ProjectIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ChatCompletionRequest"
            examples:
              chat:
                summary: "Enkel chat-completion"
                value:
                  model: gpt-4o-mini
                  messages:
                    - role: user
                      content: "Hei, Asteon!"
      responses:
        200:
          description: "Leverandørens svar, uendret."
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ChatCompletionResponse"
        401:
          "$ref": "#/components/responses/Unauthorized"
        402:
          "$ref": "#/components/responses/PaymentRequired"
        404:
          "$ref": "#/components/responses/NotFound"
        429:
          "$ref": "#/components/responses/RateLimited"
        503:
          "$ref": "#/components/responses/ServiceUnavailable"
  /external/smart/v1/chat/completions:
    post:
      tags:
        - Smart-routing
      summary: "Smart-routet chat-completion"
      description: "Be om en virtuell modell-klasse (f.eks. `best-cheap-llm`, `best-fast-llm`, `best-quality-llm`) og overlat valg av leverandør til Asteon. Returnerer responsen sammen med `X-Smart-Route-Provider` og `X-Smart-Route-Model` i headeren."
      parameters:
        - "$ref": "#/components/parameters/ProjectIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SmartRouteRequest"
      responses:
        200:
          description: "Beste leverandørs svar, med routing-info i headere."
          headers:
            X-Smart-Route-Provider:
              description: "ID-en til leverandøren som ble valgt."
              schema:
                type: string
                example: openai
            X-Smart-Route-Model:
              description: "Eksakt modell-navn som ble brukt."
              schema:
                type: string
                example: gpt-4o-mini
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ChatCompletionResponse"
        401:
          "$ref": "#/components/responses/Unauthorized"
        402:
          "$ref": "#/components/responses/PaymentRequired"
        503:
          "$ref": "#/components/responses/ServiceUnavailable"
  /portal/spend/summary:
    get:
      tags:
        - Spend
      summary: Forbrukssammendrag
      description: "Returnerer den innloggede brukerens gateway-forbruk over et tidsrom, gruppert per leverandør og per prosjekt-tag. Krever session-cookie (ikke gateway-nøkkel)."
      security:
        - sessionAuth: []
      parameters:
        - name: range
          in: query
          description: "Tidsvindu, f.eks. `7d`, `30d`, `90d`. Maks 365d."
          required: false
          schema:
            type: string
            default: 30d
            example: 30d
      responses:
        200:
          description: "Aggregerte totaler + per-provider og per-project bøtter."
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/SpendSummary"
        401:
          "$ref": "#/components/responses/Unauthorized"
  "/portal/spend/projects/{id}":
    get:
      tags:
        - Spend
      summary: "Forbruk for ett prosjekt"
      description: "Per-leverandør-nedbryting av spend for et spesifikt prosjekt-uid."
      security:
        - sessionAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: "Prosjekt-uid (f.eks. `prj_abc123`)."
          schema:
            type: string
            example: prj_abc123
        - name: range
          in: query
          required: false
          schema:
            type: string
            default: 30d
            example: 30d
      responses:
        200:
          description: "Per-leverandør spend for prosjektet."
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ProjectSpend"
        401:
          "$ref": "#/components/responses/Unauthorized"
        404:
          "$ref": "#/components/responses/NotFound"
  /portal/providers/public:
    get:
      tags:
        - Providers
      summary: "Offentlig pris-katalog"
      description: "Returnerer alle leverandører Asteon støtter med modeller, enheter, retail-priser (med 2x-margin) og rå leverandør-priser. Krever ingen autentisering."
      security: []
      responses:
        200:
          description: "Liste over alle leverandører + pris-skjema."
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ProvidersPublic"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: "agw_*"
      description: "Send `Authorization: Bearer agw_din_nokkel`. Generer nøkler under [/developers](https://asteon.ai/developers)."
    sessionAuth:
      type: apiKey
      in: cookie
      name: asteon_session
      description: "Session-cookie satt etter innlogging. Brukes for portal-API-er."
  parameters:
    ProjectIdHeader:
      name: X-Asteon-Project-Id
      in: header
      required: false
      description: "Valgfri prosjekt-tag. Hvis satt blir kostnaden bokført mot prosjektet i forbruksrapporten. Du må ha rolle på prosjektet — ellers ignoreres taggen."
      schema:
        type: string
        example: prj_abc123
  schemas:
    ChatCompletionRequest:
      type: object
      required:
        - model
        - messages
      properties:
        model:
          type: string
          example: gpt-4o-mini
        messages:
          type: array
          items:
            type: object
            required:
              - role
              - content
            properties:
              role:
                type: string
                enum:
                  - system
                  - user
                  - assistant
                  - tool
              content:
                type: string
        stream:
          type: boolean
          default: false
          description: "Hvis `true`, returneres svaret som SSE."
        temperature:
          type: number
          minimum: 0
          maximum: 2
        max_tokens:
          type: integer
          minimum: 1
    ChatCompletionResponse:
      type: object
      properties:
        id:
          type: string
          example: chatcmpl-abc123
        object:
          type: string
          example: chat.completion
        model:
          type: string
          example: gpt-4o-mini
        choices:
          type: array
          items:
            type: object
            properties:
              index:
                type: integer
              message:
                type: object
                properties:
                  role:
                    type: string
                    example: assistant
                  content:
                    type: string
                    example: "Hei! Hva kan jeg hjelpe deg med?"
              finish_reason:
                type: string
                example: stop
        usage:
          type: object
          properties:
            prompt_tokens:
              type: integer
            completion_tokens:
              type: integer
            total_tokens:
              type: integer
    SmartRouteRequest:
      allOf:
        - "$ref": "#/components/schemas/ChatCompletionRequest"
        - type: object
          properties:
            model:
              type: string
              description: "Virtuell modell-klasse."
              enum:
                - best-cheap-llm
                - best-fast-llm
                - best-quality-llm
              example: best-cheap-llm
    SpendSummary:
      type: object
      properties:
        range:
          type: object
          properties:
            days:
              type: integer
              example: 30
            since:
              type: string
              format: date-time
        totals:
          type: object
          properties:
            calls:
              type: integer
              example: 1284
            failures:
              type: integer
              example: 12
            rawCost:
              type: number
              example: 4.21
            customerCost:
              type: number
              example: 8.42
        byProvider:
          type: array
          items:
            type: object
            properties:
              providerId:
                type: string
                example: openai
              calls:
                type: integer
              failures:
                type: integer
              rawCost:
                type: number
              customerCost:
                type: number
        byProject:
          type: array
          items:
            type: object
            properties:
              projectId:
                type:
                  - string
                  - "null"
                example: prj_abc123
              projectName:
                type: string
                example: "Mitt eventyrspill"
              calls:
                type: integer
              failures:
                type: integer
              rawCost:
                type: number
              customerCost:
                type: number
    ProjectSpend:
      type: object
      properties:
        project:
          type: object
          properties:
            uid:
              type: string
            name:
              type: string
        range:
          type: object
          properties:
            days:
              type: integer
            since:
              type: string
              format: date-time
        totals:
          type: object
          properties:
            calls:
              type: integer
            rawCost:
              type: number
            customerCost:
              type: number
        byProvider:
          type: array
          items:
            type: object
            properties:
              providerId:
                type: string
              calls:
                type: integer
              rawCost:
                type: number
              customerCost:
                type: number
    ProvidersPublic:
      type: object
      properties:
        providers:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                example: openai
              description:
                type: string
              category:
                type: string
                enum:
                  - LLM
                  - Image
                  - Video
                  - Audio
                  - Search
                  - 3D
                  - Other
              baseUrl:
                type: string
                format: uri
              hasKey:
                type: boolean
              effectiveMargin:
                type: number
                example: 2
              pricing:
                type: object
                properties:
                  kind:
                    type: string
                    enum:
                      - llm
                      - units
                  currency:
                    type: string
                    example: USD
                  models:
                    type: array
                    items:
                      type: object
                      properties:
                        model:
                          type: string
                        inputPer1M:
                          type: number
                        outputPer1M:
                          type: number
                        cachedInputPer1M:
                          type: number
                        inputPer1MRetail:
                          type: number
                        outputPer1MRetail:
                          type: number
                  units:
                    type: array
                  lastUpdated:
                    type: string
                    format: date
                  sourceUrl:
                    type: string
                    format: uri
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          example: "Authentication required"
        code:
          type: string
          example: UNAUTHORIZED
  responses:
    Unauthorized:
      description: "Manglende eller ugyldig nøkkel."
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
    PaymentRequired:
      description: "Lommeboken har ikke nok saldo."
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
    NotFound:
      description: "Ressurs eller leverandør finnes ikke."
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
    RateLimited:
      description: "Leverandøren har returnert 429."
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
    ServiceUnavailable:
      description: "Alle smart-route-kandidater feilet eller leverandør er nede."
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/Error"
