{
  "openapi": "3.1.0",
  "info": {
    "title": "Simplio.dev API",
    "version": "1.0.0",
    "description": "AI Gateway Proxy — one key, all providers. OpenAI-compatible API with Smart Fallback, Eco-mode, and usage tracking.",
    "contact": {
      "name": "Simplio.dev",
      "url": "https://simplio.dev"
    }
  },
  "servers": [
    {
      "url": "https://simplio.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "summary": "Create a chat completion",
        "description": "Sends a chat completion request through the Simplio gateway. Routes to the appropriate provider (OpenAI, Anthropic, DeepSeek) based on the model specified. Always returns a streaming SSE response.",
        "tags": ["Chat"],
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "X-Simplio-No-Eco",
            "in": "header",
            "required": false,
            "schema": { "type": "string", "enum": ["true"] },
            "description": "Set to \"true\" to skip Eco-mode routing for this request. Forces the default provider (OpenAI) even when Eco-mode is enabled. Pro feature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Streaming SSE response with chat completion chunks",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Server-Sent Events stream. Each event is `data: {json}` followed by `data: [DONE]`."
                }
              }
            },
            "headers": {
              "x-trace-id": {
                "schema": { "type": "string" },
                "description": "Unique trace ID for request tracking"
              },
              "x-provider": {
                "schema": { "type": "string" },
                "description": "Provider that handled the request (openai, anthropic, deepseek)"
              },
              "x-model": {
                "schema": { "type": "string" },
                "description": "Model used for the completion"
              },
              "x-fallback": {
                "schema": { "type": "string", "enum": ["true", "false"] },
                "description": "Whether Smart Fallback was activated"
              },
              "x-eco-mode": {
                "schema": { "type": "string", "enum": ["true", "false"] },
                "description": "Whether Eco-mode routing was used"
              },
              "x-ratelimit-limit": {
                "schema": { "type": "string" },
                "description": "Rate limit ceiling for this window"
              },
              "x-ratelimit-remaining": {
                "schema": { "type": "string" },
                "description": "Remaining requests in this window"
              },
              "x-ratelimit-reset": {
                "schema": { "type": "string" },
                "description": "Unix timestamp when the rate limit resets"
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "402": {
            "description": "Smart Fallback requires Pro plan",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "403": {
            "description": "API key expired (after rotation grace period)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "413": {
            "description": "Request body too large (max 100KB)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "422": {
            "description": "No provider API key configured or decryption failed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (burst or monthly)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": { "type": "string" },
                "description": "Seconds until rate limit resets"
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "502": {
            "description": "Provider error — upstream provider returned an error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      },
      "options": {
        "operationId": "chatCompletionsCors",
        "summary": "CORS preflight",
        "description": "Returns CORS headers for browser-based clients.",
        "tags": ["Chat"],
        "security": [],
        "responses": {
          "204": {
            "description": "No content — CORS headers returned",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": { "type": "string", "example": "*" }
              },
              "Access-Control-Allow-Methods": {
                "schema": { "type": "string", "example": "POST, OPTIONS" }
              },
              "Access-Control-Allow-Headers": {
                "schema": { "type": "string", "example": "Content-Type, Authorization, Idempotency-Key, X-Simplio-No-Eco" }
              }
            }
          }
        }
      }
    },
    "/api/v1/embeddings": {
      "post": {
        "operationId": "createEmbedding",
        "summary": "Create embeddings",
        "description": "Generate vector embeddings for text input. Proxied to OpenAI. Requires an OpenAI API key configured in the dashboard.",
        "tags": ["Embeddings"],
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmbeddingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Embedding response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/EmbeddingResponse" }
              }
            },
            "headers": {
              "x-trace-id": {
                "schema": { "type": "string" },
                "description": "Unique trace ID for request tracking"
              },
              "x-provider": {
                "schema": { "type": "string" },
                "description": "Provider that handled the request (always openai)"
              }
            }
          },
          "400": {
            "description": "Invalid request body or missing input",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "422": {
            "description": "No OpenAI API key configured",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "502": {
            "description": "OpenAI returned an error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      },
      "options": {
        "operationId": "embeddingsCors",
        "summary": "CORS preflight",
        "description": "Returns CORS headers for browser-based clients.",
        "tags": ["Embeddings"],
        "security": [],
        "responses": {
          "204": {
            "description": "No content — CORS headers returned"
          }
        }
      }
    },
    "/api/v1/models": {
      "get": {
        "operationId": "listModels",
        "summary": "List available models",
        "description": "Returns a list of models available to the authenticated user, based on their configured provider API keys.",
        "tags": ["Models"],
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "List of available models",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ModelsResponse" }
              }
            },
            "headers": {
              "x-trace-id": {
                "schema": { "type": "string" },
                "description": "Unique trace ID for request tracking"
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "403": {
            "description": "API key deactivated or expired",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      },
      "options": {
        "operationId": "modelsCors",
        "summary": "CORS preflight",
        "description": "Returns CORS headers for browser-based clients.",
        "tags": ["Models"],
        "security": [],
        "responses": {
          "204": {
            "description": "No content — CORS headers returned"
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Health check",
        "description": "Returns service health status.",
        "tags": ["Health"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "ok" },
                    "timestamp": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/health/deep": {
      "get": {
        "operationId": "deepHealthCheck",
        "summary": "Deep health check",
        "description": "Checks service health including database connectivity.",
        "tags": ["Health"],
        "security": [],
        "responses": {
          "200": {
            "description": "All systems healthy",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DeepHealthResponse" }
              }
            }
          },
          "503": {
            "description": "Service degraded",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DeepHealthResponse" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Master key in format `sk_simplio_...`. Generate at https://simplio.dev/dashboard"
      }
    },
    "schemas": {
      "ChatCompletionRequest": {
        "type": "object",
        "required": ["messages"],
        "properties": {
          "model": {
            "type": "string",
            "default": "gpt-4o",
            "description": "Model to use for the completion.",
            "enum": [
              "gpt-4o",
              "gpt-4o-mini",
              "gpt-4-turbo",
              "o1",
              "o1-mini",
              "claude-4-sonnet",
              "claude-4-haiku",
              "deepseek-chat",
              "deepseek-reasoner"
            ]
          },
          "messages": {
            "type": "array",
            "description": "Array of message objects.",
            "items": {
              "$ref": "#/components/schemas/Message"
            },
            "minItems": 1
          },
          "temperature": {
            "type": "number",
            "minimum": 0,
            "maximum": 2,
            "description": "Sampling temperature. Higher = more random."
          },
          "max_tokens": {
            "type": "integer",
            "default": 4096,
            "description": "Maximum number of tokens to generate."
          },
          "stream": {
            "type": "boolean",
            "default": true,
            "description": "Always true — Simplio only supports streaming responses."
          }
        }
      },
      "Message": {
        "type": "object",
        "required": ["role", "content"],
        "properties": {
          "role": {
            "type": "string",
            "enum": ["system", "user", "assistant"],
            "description": "The role of the message author."
          },
          "content": {
            "type": "string",
            "description": "The content of the message."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string",
                "description": "Human-readable error description."
              },
              "type": {
                "type": "string",
                "example": "simplio_error"
              },
              "code": {
                "type": "integer",
                "description": "HTTP status code."
              },
              "trace_id": {
                "type": "string",
                "description": "Unique trace ID for support."
              }
            }
          }
        }
      },
      "EmbeddingRequest": {
        "type": "object",
        "required": ["input"],
        "properties": {
          "model": {
            "type": "string",
            "default": "text-embedding-3-small",
            "description": "Embedding model to use.",
            "enum": [
              "text-embedding-3-small",
              "text-embedding-3-large",
              "text-embedding-ada-002"
            ]
          },
          "input": {
            "oneOf": [
              { "type": "string" },
              { "type": "array", "items": { "type": "string" }, "minItems": 1 }
            ],
            "description": "Text to embed — a string or array of strings."
          },
          "encoding_format": {
            "type": "string",
            "enum": ["float", "base64"],
            "description": "Output format for embeddings."
          },
          "dimensions": {
            "type": "integer",
            "description": "Number of dimensions for the output embedding."
          }
        }
      },
      "EmbeddingResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": { "type": "string", "example": "embedding" },
                "index": { "type": "integer" },
                "embedding": {
                  "type": "array",
                  "items": { "type": "number" }
                }
              }
            }
          },
          "model": { "type": "string" },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": { "type": "integer" },
              "total_tokens": { "type": "integer" }
            }
          }
        }
      },
      "ModelsResponse": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ModelObject" }
          }
        }
      },
      "ModelObject": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "description": "Model identifier." },
          "object": { "type": "string", "example": "model" },
          "created": { "type": "integer", "description": "Unix timestamp of model creation." },
          "owned_by": { "type": "string", "description": "Provider that owns the model." }
        }
      },
      "DeepHealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "degraded"]
          },
          "checks": {
            "type": "object",
            "properties": {
              "database": {
                "type": "string",
                "enum": ["ok", "error"]
              }
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}
