{
  "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" } } }
      }
    }
  }
}
