{
  "openapi": "3.1.0",
  "info": {
    "title": "MaxAI API",
    "version": "1.0.0",
    "summary": "OpenAI-compatible LLM API gateway (200+ models, 40+ providers).",
    "description": "MaxAI is a developer-focused LLM API gateway built on top of 9Router. The `/v1/*` surface is OpenAI-compatible — point any OpenAI SDK at the base URL and use a `maxai-...` API key.\n\n* **Auth:** `Authorization: Bearer maxai-...` (your dashboard API key)\n* **Rate limits:** per-customer (tier-based) and per-provider\n* **Streaming:** `text/event-stream` supported on chat completions\n* **Real-time:** customer-scoped events over WebSocket at `/socket.io/`\n",
    "contact": {
      "name": "MaxAI",
      "url": "https://github.com/supasapasa/maxai-dashboard"
    },
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    }
  },
  "servers": [
    { "url": "http://104.215.144.10", "description": "Production VM (HTTP)" }
  ],
  "tags": [
    { "name": "Health",      "description": "Service health probes." },
    { "name": "Auth",        "description": "Customer registration, login, token refresh." },
    { "name": "Customer",    "description": "Profile and billing for the authenticated customer." },
    { "name": "Keys",        "description": "API key lifecycle." },
    { "name": "Usage",       "description": "Per-customer usage analytics." },
    { "name": "Models",      "description": "Model catalog + performance metrics." },
    { "name": "Templates",   "description": "Workflow templates (built-in + per-customer)." },
    { "name": "v1",          "description": "OpenAI-compatible LLM proxy." }
  ],
  "components": {
    "securitySchemes": {
      "BearerJWT":   { "type": "http", "scheme": "bearer", "bearerFormat": "JWT",
                       "description": "Customer dashboard JWT (from `/api/auth/login`)." },
      "ApiKey":      { "type": "http", "scheme": "bearer",
                       "description": "Gateway API key in the form `maxai-...` for `/v1/*` routes." }
    },
    "schemas": {
      "Health":         { "type": "object", "properties": {
        "service":        { "type": "string", "example": "maxai-dashboard" },
        "status":         { "type": "string", "example": "ok" },
        "timestamp":      { "type": "string", "format": "date-time" },
        "uptime_seconds": { "type": "number" }
      }},
      "RegisterRequest": { "type": "object", "required": ["email", "password", "name"],
        "properties": {
          "email":    { "type": "string", "format": "email" },
          "password": { "type": "string", "minLength": 8 },
          "name":     { "type": "string" }
        }
      },
      "LoginRequest":   { "type": "object", "required": ["email", "password"],
        "properties": {
          "email":    { "type": "string", "format": "email" },
          "password": { "type": "string" },
          "totp":     { "type": "string", "description": "Required if 2FA is enabled." }
        }
      },
      "TokenPair":      { "type": "object",
        "properties": {
          "access_token":  { "type": "string" },
          "refresh_token": { "type": "string" },
          "customer":      { "type": "object", "additionalProperties": true }
        }
      },
      "ApiKeyCreate":   { "type": "object", "required": ["name"],
        "properties": {
          "name":            { "type": "string" },
          "rate_limit_rpm":  { "type": "integer", "minimum": 0 },
          "rate_limit_rpd":  { "type": "integer", "minimum": 0 },
          "budget":          { "type": "number", "nullable": true,
                               "description": "Optional USD budget. When exceeded, the key starts returning HTTP 402." }
        }
      },
      "ApiKey":         { "type": "object",
        "properties": {
          "id":              { "type": "integer" },
          "name":            { "type": "string" },
          "key":             { "type": "string", "description": "Plaintext key, returned only once on create." },
          "key_prefix":      { "type": "string", "example": "maxai-abc123" },
          "status":          { "type": "string", "enum": ["active", "disabled"] },
          "rate_limit_rpm":  { "type": "integer" },
          "rate_limit_rpd":  { "type": "integer" },
          "total_requests":  { "type": "integer" },
          "total_tokens":    { "type": "integer" },
          "total_cost":      { "type": "number" },
          "budget":          { "type": "number", "nullable": true },
          "budget_used":     { "type": "number" },
          "created_at":      { "type": "string", "format": "date-time" }
        }
      },
      "ChatCompletionRequest": { "type": "object", "required": ["model", "messages"],
        "properties": {
          "model":      { "type": "string", "example": "gpt-4o-mini" },
          "messages":   { "type": "array", "items": { "type": "object" } },
          "stream":     { "type": "boolean", "default": false },
          "temperature":{ "type": "number" },
          "max_tokens": { "type": "integer" }
        }
      },
      "ModelMetric":    { "type": "object",
        "properties": {
          "model":              { "type": "string" },
          "requests":           { "type": "integer" },
          "success":            { "type": "integer" },
          "errors":             { "type": "integer" },
          "success_rate":       { "type": "number" },
          "tokens_in":          { "type": "integer" },
          "tokens_out":         { "type": "integer" },
          "total_tokens":       { "type": "integer" },
          "total_cost":         { "type": "number" },
          "cost_per_1k_tokens": { "type": "number" },
          "avg_latency_ms":     { "type": "number" }
        }
      },
      "Template":       { "type": "object",
        "properties": {
          "id":            { "type": "integer" },
          "slug":          { "type": "string" },
          "name":          { "type": "string" },
          "category":      { "type": "string" },
          "description":   { "type": "string" },
          "default_model": { "type": "string" },
          "system_prompt": { "type": "string" },
          "user_prompt":   { "type": "string" },
          "parameters":    { "type": "object", "additionalProperties": true },
          "variables":     { "type": "array",  "items": { "type": "object" } },
          "is_builtin":    { "type": "boolean" },
          "runs":          { "type": "integer" }
        }
      },
      "Error":          { "type": "object",
        "properties": {
          "error":    { "type": "string" },
          "details":  { "type": "string" }
        }
      }
    }
  },
  "paths": {
    "/api/health":             { "get": { "tags": ["Health"], "summary": "Service liveness probe",
      "responses": { "200": { "description": "OK",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Health" } } } } } } },
    "/api/realtime/health":    { "get": { "tags": ["Health"], "summary": "WebSocket layer health",
      "responses": { "200": { "description": "OK" } } } },
    "/api/auth/register":      { "post": { "tags": ["Auth"], "summary": "Create a new customer account",
      "requestBody": { "required": true,
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequest" } } } },
      "responses": { "201": { "description": "Created",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenPair" } } } },
        "400": { "description": "Validation error",
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } },
    "/api/auth/login":         { "post": { "tags": ["Auth"], "summary": "Login with email + password",
      "requestBody": { "required": true,
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } } },
      "responses": { "200": { "description": "OK",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenPair" } } } },
        "401": { "description": "Invalid credentials" } } } },
    "/api/auth/refresh":       { "post": { "tags": ["Auth"], "summary": "Refresh the access token",
      "security": [{ "BearerJWT": [] }],
      "responses": { "200": { "description": "New access token issued" } } } },
    "/api/customer/profile":   {
      "get":  { "tags": ["Customer"], "summary": "Get the authenticated customer's profile",
        "security": [{ "BearerJWT": [] }],
        "responses": { "200": { "description": "OK" } } },
      "put":  { "tags": ["Customer"], "summary": "Update the authenticated customer's profile",
        "security": [{ "BearerJWT": [] }],
        "responses": { "200": { "description": "Updated" } } }
    },
    "/api/keys":               {
      "get":  { "tags": ["Keys"], "summary": "List the caller's API keys",
        "security": [{ "BearerJWT": [] }],
        "responses": { "200": { "description": "OK",
          "content": { "application/json": { "schema": { "type": "object", "properties": { "keys": { "type": "array",
            "items": { "$ref": "#/components/schemas/ApiKey" } } } } } } } } },
      "post": { "tags": ["Keys"], "summary": "Create a new API key (returns plaintext once)",
        "security": [{ "BearerJWT": [] }],
        "requestBody": { "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKeyCreate" } } } },
        "responses": { "201": { "description": "Created",
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } } } }
    },
    "/api/keys/{key_id}":      { "delete": { "tags": ["Keys"], "summary": "Revoke an API key",
      "security": [{ "BearerJWT": [] }],
      "parameters": [{ "name": "key_id", "in": "path", "required": true, "schema": { "type": "integer" } }],
      "responses": { "200": { "description": "Revoked" } } } },
    "/api/usage/stats":        { "get": { "tags": ["Usage"], "summary": "Aggregate usage stats for the caller",
      "security": [{ "BearerJWT": [] }],
      "parameters": [{ "name": "days", "in": "query", "required": false,
        "schema": { "type": "integer", "default": 30 } }],
      "responses": { "200": { "description": "OK" } } } },
    "/api/usage/recent":       { "get": { "tags": ["Usage"], "summary": "Recent request logs (paginated)",
      "security": [{ "BearerJWT": [] }],
      "parameters": [
        { "name": "page",     "in": "query", "schema": { "type": "integer", "default": 1 } },
        { "name": "per_page", "in": "query", "schema": { "type": "integer", "default": 50 } }
      ],
      "responses": { "200": { "description": "OK" } } } },
    "/api/models":             { "get": { "tags": ["Models"], "summary": "Dashboard model catalog (with pricing)",
      "responses": { "200": { "description": "OK" } } } },
    "/api/models/metrics":     { "get": { "tags": ["Models"], "summary": "Per-model performance metrics",
      "parameters": [
        { "name": "window", "in": "query",
          "schema": { "type": "string", "enum": ["1h", "24h", "7d", "30d"], "default": "24h" } },
        { "name": "limit",  "in": "query", "schema": { "type": "integer", "default": 50 } }
      ],
      "responses": { "200": { "description": "OK",
        "content": { "application/json": { "schema": { "type": "object", "properties": {
          "window":    { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" },
          "models":    { "type": "array", "items": { "$ref": "#/components/schemas/ModelMetric" } }
        } } } } } } } },
    "/api/models/leaderboards": { "get": { "tags": ["Models"], "summary": "Top models by volume / latency / cost / tokens",
      "parameters": [
        { "name": "window", "in": "query", "schema": { "type": "string", "enum": ["1h", "24h", "7d", "30d"], "default": "24h" } },
        { "name": "top",    "in": "query", "schema": { "type": "integer", "default": 10 } }
      ],
      "responses": { "200": { "description": "OK" } } } },
    "/api/templates":          { "get": { "tags": ["Templates"], "summary": "List built-in + caller's personal templates",
      "responses": { "200": { "description": "OK",
        "content": { "application/json": { "schema": { "type": "object", "properties": {
          "count":     { "type": "integer" },
          "templates": { "type": "array", "items": { "$ref": "#/components/schemas/Template" } }
        } } } } } } } },
    "/api/templates/{template_id}":         { "get": { "tags": ["Templates"], "summary": "Template detail",
      "parameters": [{ "name": "template_id", "in": "path", "required": true, "schema": { "type": "integer" } }],
      "responses": { "200": { "description": "OK" } } } },
    "/api/templates/{template_id}/render":  { "post": { "tags": ["Templates"], "summary": "Preview rendered messages",
      "parameters": [{ "name": "template_id", "in": "path", "required": true, "schema": { "type": "integer" } }],
      "requestBody": { "required": true,
        "content": { "application/json": { "schema": { "type": "object", "properties": {
          "variables": { "type": "object", "additionalProperties": true },
          "model":     { "type": "string" }
        } } } } },
      "responses": { "200": { "description": "OK" }, "400": { "description": "Missing variable" } } } },
    "/api/templates/{template_id}/run":     { "post": { "tags": ["Templates"], "summary": "Execute template against the gateway",
      "security": [{ "BearerJWT": [] }],
      "parameters": [{ "name": "template_id", "in": "path", "required": true, "schema": { "type": "integer" } }],
      "requestBody": { "required": true,
        "content": { "application/json": { "schema": { "type": "object", "required": ["api_key"],
          "properties": {
            "api_key":   { "type": "string", "description": "Your `maxai-...` gateway API key." },
            "model":     { "type": "string" },
            "variables": { "type": "object", "additionalProperties": true }
          } } } } },
      "responses": { "200": { "description": "OK" }, "400": { "description": "Validation error" } } } },
    "/v1/models":              { "get": { "tags": ["v1"], "summary": "OpenAI-compatible model list",
      "security": [{ "ApiKey": [] }],
      "responses": { "200": { "description": "OK" } } } },
    "/v1/chat/completions":    { "post": { "tags": ["v1"], "summary": "OpenAI-compatible chat completions (proxy to 9Router)",
      "security": [{ "ApiKey": [] }],
      "requestBody": { "required": true,
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChatCompletionRequest" } } } },
      "responses": {
        "200": { "description": "OK (JSON or text/event-stream depending on `stream`)" },
        "401": { "description": "Invalid API key" },
        "402": { "description": "Insufficient balance or budget exhausted" },
        "429": { "description": "Rate limited (per-customer or per-provider)" }
      } } }
  }
}
