By default, the API documentation endpoints (/docs, /redoc, /openapi.json) are exempt from authentication. This document explains the security implications and how to configure them.
| Endpoint | Purpose | Exempt? |
|---|---|---|
/health |
Health check | ✅ Always |
/docs |
Swagger UI (interactive docs) | ✅ Configurable |
/redoc |
ReDoc UI (alternative docs) | ✅ Configurable |
/openapi.json |
OpenAPI specification | ✅ Configurable |
When docs are public (exempt from auth), anyone can access:
- ✅ API endpoint paths (
/api/v1/chat/completions, etc.) - ✅ Request/response schemas
- ✅ Parameter names and types
- ✅ Model definitions
- ✅ Available tools and functions
Documentation endpoints cannot:
- ❌ Execute API calls without authentication
- ❌ Access your data
- ❌ See your API keys or tokens
- ❌ Bypass authentication on actual API endpoints
The Swagger UI at /docs has interactive "Try it out" buttons:
Important: These buttons still require authentication!
When someone clicks "Try it out" and executes a request:
- Request goes through normal authentication middleware
- Without valid token → Returns 401 Unauthorized
- With valid token → Request succeeds
Example in Swagger UI:
POST /api/v1/chat/completions
[Try it out] button
↓
User enters request body
↓
Clicks "Execute"
↓
Request sent WITHOUT token (if not provided)
↓
Middleware checks authentication
↓
Returns: 401 Unauthorized ❌
Use when:
- You want developers to easily explore your API
- You're using Traefik BasicAuth to protect the entire service
- Your API is meant to be publicly documented
- You don't consider API structure sensitive
Configuration:
XAI_API_AUTH=true
XAI_API_AUTH_TOKEN=your_token
XAI_API_AUTH_EXCLUDE_DOCS=true # Docs are publicAccess:
https://api.domain.com/docs- ✅ No auth neededhttps://api.domain.com/api/v1/chat/completions- 🔒 Requires token
Pros:
- Easy for developers to discover API
- Standard practice for public APIs
- Can test endpoints right in browser (if they provide token)
Cons:
- Reveals API structure
- Shows all available endpoints
- Could give attackers reconnaissance information
Use when:
- Your API is internal/private
- You don't want API structure publicly visible
- Maximum security is priority
- You have a small known set of users
Configuration:
XAI_API_AUTH=true
XAI_API_AUTH_TOKEN=your_token
XAI_API_AUTH_EXCLUDE_DOCS=false # Docs require authAccess:
https://api.domain.com/docs- 🔒 Requires tokenhttps://api.domain.com/api/v1/chat/completions- 🔒 Requires token
How to access docs with token:
Method 1: Use Swagger UI's Authorize Button
- Go to
/docs - Get 401 error in browser
- If using custom header, you'll need Method 2
Method 2: Browser Extension (Recommended)
Install a browser extension that adds custom headers:
- Chrome: "ModHeader" or "Simple Modify Headers"
- Firefox: "Modify Header Value"
Configure it to add:
- If using
Authorizationheader:Authorization: Bearer your_token - If using custom header:
X-API-Token: your_token
Method 3: Local Proxy
Run a local proxy that injects the auth header:
# auth_proxy.py
from flask import Flask, request, Response
import requests
app = Flask(__name__)
TOKEN = "your_token_here"
API_BASE = "http://localhost:8000"
HEADER_NAME = "X-API-Token" # or "Authorization"
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def proxy(path):
headers = dict(request.headers)
if HEADER_NAME == "Authorization":
headers['Authorization'] = f'Bearer {TOKEN}'
else:
headers[HEADER_NAME] = TOKEN
resp = requests.request(
method=request.method,
url=f"{API_BASE}/{path}",
headers=headers,
data=request.get_data(),
allow_redirects=False
)
return Response(resp.content, resp.status_code, resp.raw.headers.items())
if __name__ == '__main__':
app.run(port=8080)Then access docs at http://localhost:8080/docs
Use when:
- You want docs accessible but not completely public
- You're using Coolify with Traefik
- You want browser-friendly authentication for docs
Configuration:
# App auth for API endpoints
XAI_API_AUTH=true
XAI_API_AUTH_TOKEN=api_token_here
XAI_API_AUTH_HEADER=X-API-Token
XAI_API_AUTH_EXCLUDE_DOCS=true # Docs exempt from app auth
# Traefik BasicAuth in Coolify
# (Enable in Coolify UI)Result:
- All endpoints protected by Traefik BasicAuth (including docs)
- API endpoints additionally require
X-API-Token - Docs accessible with just BasicAuth
- Browser prompts for username/password
Access:
# Access docs - only BasicAuth needed
curl -u "admin:password" https://api.domain.com/docs
# Use API - needs both
curl -u "admin:password" \
-H "X-API-Token: api_token" \
https://api.domain.com/api/v1/chat/completionsXAI_API_AUTH=true
XAI_API_AUTH_EXCLUDE_DOCS=true # Public docs+ Use Traefik BasicAuth for additional protection
XAI_API_AUTH=true
XAI_API_AUTH_EXCLUDE_DOCS=false # Protected docs# App-level auth
XAI_API_AUTH=true
XAI_API_AUTH_HEADER=X-API-Token
XAI_API_AUTH_EXCLUDE_DOCS=false # Docs require token
# + Traefik BasicAuth in Coolify
# + IP whitelisting at firewall level
# + Rate limiting (already enabled)# Start server with public docs
XAI_API_AUTH=true \
XAI_API_AUTH_TOKEN=test123 \
XAI_API_AUTH_EXCLUDE_DOCS=true \
uvicorn app.main:app --reload
# Access docs (should work)
curl http://localhost:8000/docs
# Returns: Swagger UI HTML ✅
# Access API without token (should fail)
curl http://localhost:8000/api/v1/chat/completions
# Returns: 401 Unauthorized ❌# Start server with protected docs
XAI_API_AUTH=true \
XAI_API_AUTH_TOKEN=test123 \
XAI_API_AUTH_EXCLUDE_DOCS=false \
uvicorn app.main:app --reload
# Access docs without token (should fail)
curl http://localhost:8000/docs
# Returns: 401 Unauthorized ❌
# Access docs with token (should work)
curl -H "Authorization: Bearer test123" http://localhost:8000/docs
# Returns: Swagger UI HTML ✅A: No. The "Try it out" buttons in Swagger UI send requests that still go through authentication middleware. Without a valid token, they get 401 errors.
A: No. Documentation endpoints never reveal your XAI_API_KEY or XAI_API_AUTH_TOKEN. They only show the API structure.
A: It depends:
- Public API (like Stripe, Twilio) → Public docs are standard
- Internal API (company private) → Protect docs
- Personal project → Use BasicAuth at minimum
A: Always public. The health endpoint is always exempt from authentication because:
- Load balancers need it for health checks
- Monitoring tools need it without auth
- It reveals no sensitive information
- Standard practice for all APIs
A: Not recommended. If you absolutely need to:
- Remove
/healthfrom exempt paths in middleware - Configure your load balancer to use authenticated health checks
- Be aware this complicates deployment
| Configuration | Docs Access | API Access | Use Case |
|---|---|---|---|
EXCLUDE_DOCS=true |
🌐 Public | 🔒 Auth required | Public APIs, with Traefik BasicAuth |
EXCLUDE_DOCS=false |
🔒 Auth required | 🔒 Auth required | Private/internal APIs |
| With Traefik BasicAuth | 🔒 BasicAuth | 🔒 BasicAuth + Token | Maximum security |
Recommended production setup:
# In Coolify
XAI_API_AUTH=true
XAI_API_AUTH_TOKEN=secure-random-token
XAI_API_AUTH_HEADER=X-API-Token
XAI_API_AUTH_EXCLUDE_DOCS=true # Docs still accessible
# Enable Traefik BasicAuth in Coolify UI
# This protects EVERYTHING including docsResult:
- Docs protected by BasicAuth (browser-friendly)
- API endpoints require BasicAuth + Token
- Defense in depth
- Easy for authorized developers to explore