diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 9c29927c5cb..15a5ed48cdb 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -1498,6 +1498,22 @@ if docs_url != "/" and root_redirect_url is not None: return RedirectResponse(url=root_redirect_url) # type: ignore[arg-type] +@app.get("/version", tags=["info"]) +async def get_version(): + """Return the LiteLLM version. Unprotected for easy deployment checks.""" + return {"version": version} + + +@app.get("/info", tags=["info"]) +async def get_info(): + """Return API info (title, description, version). Matches OpenAPI info structure.""" + return { + "title": _title, + "description": _description, + "version": version, + } + + from typing import Dict user_api_base = None diff --git a/tests/proxy_unit_tests/test_proxy_server.py b/tests/proxy_unit_tests/test_proxy_server.py index 61a2f3055af..6eeb54ec3b7 100644 --- a/tests/proxy_unit_tests/test_proxy_server.py +++ b/tests/proxy_unit_tests/test_proxy_server.py @@ -852,6 +852,29 @@ def test_health(client_no_auth): pytest.fail(f"LiteLLM Proxy test failed. Exception - {str(e)}") +def test_version_endpoint(client_no_auth): + """Test that /version returns LiteLLM version. Unprotected for deployment checks.""" + response = client_no_auth.get("/version") + assert response.status_code == 200 + data = response.json() + assert "version" in data + assert isinstance(data["version"], str) + assert len(data["version"]) > 0 + + +def test_info_endpoint(client_no_auth): + """Test that /info returns API info (title, description, version). Matches OpenAPI info.""" + response = client_no_auth.get("/info") + assert response.status_code == 200 + data = response.json() + assert "title" in data + assert "description" in data + assert "version" in data + assert isinstance(data["title"], str) + assert isinstance(data["description"], str) + assert isinstance(data["version"], str) + + # test_add_new_model() from litellm.integrations.custom_logger import CustomLogger