Overview
The API Proxy is a high-performance local server that converts Google AI accounts into standard API endpoints. It supports multiple protocols including OpenAI, Anthropic (Claude), and native Gemini formats.
Supported Protocols
OpenAI Compatible
Provides /v1/chat/completions endpoint compatible with 99% of existing AI applications:
import openai
client = openai.OpenAI(
api_key="sk-antigravity",
base_url="http://127.0.0.1:8045/v1"
)
response = client.chat.completions.create(
model="gemini-3-flash",
messages=[{"role": "user", "content": "Hello"}]
)
print(response.choices[0].message.content)
Anthropic (Claude) Protocol
Native /v1/messages interface with full Claude Code CLI support:
from anthropic import Anthropic
client = Anthropic(
base_url="http://127.0.0.1:8045",
api_key="sk-antigravity"
)
response = client.messages.create(
model="gemini-3-flash",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}]
)
print(response.content[0].text)
Gemini Native Protocol
Direct Google SDK compatibility:
import google.generativeai as genai
genai.configure(
api_key="sk-antigravity",
transport='rest',
client_options={'api_endpoint': 'http://127.0.0.1:8045'}
)
model = genai.GenerativeModel('gemini-3-flash')
response = model.generate_content("Hello")
print(response.text)
Server Configuration
Basic Settings
// From src/pages/ApiProxy.tsx:1144
interface ProxyConfig {
port: number; // Default: 8045
request_timeout: number; // Default: 120s
auto_start: boolean; // Start on app launch
allow_lan_access: boolean; // Enable network access
}
Port Configuration
Timeout Settings
Auto-Start
// From src-tauri/src/proxy/server.rs:695
let addr = format!("{}:{}", host, port);
let listener = tokio::net::TcpListener::bind(&addr).await?;
Port must be between 8000-65535. Requires restart if proxy is running.
Configure request timeout (30-7200 seconds):updateProxyConfig({ request_timeout: 300 }); // 5 minutes
Very long timeouts may cause connection issues with some clients.
Enable automatic proxy startup on application launch:updateProxyConfig({ auto_start: true });
Authentication
The proxy uses API key authentication for security:
// From src-tauri/src/proxy/middleware.rs
pub async fn auth_middleware(
State(state): State<AppState>,
headers: HeaderMap,
request: Request,
next: Next,
) -> Response {
// Extract API key from Authorization header
let api_key = extract_api_key(&headers);
// Validate against configured key
}
Generating API Keys
Navigate to API Proxy Settings
Open the API Proxy page in the application.
Generate New Key
Click Regenerate API Key to create a new authentication key.
Copy and Use
Copy the generated key and use it in your API clients.
Regenerating the API key will invalidate all existing client connections.
Token Management
The proxy automatically manages account tokens and handles rotation:
// From src-tauri/src/proxy/token_manager.rs:969
pub async fn get_token(
&self,
quota_group: &str,
force_rotate: bool,
session_id: Option<&str>,
target_model: &str,
) -> Result<(String, String, String, String, u64), String>
Smart Token Selection
The token manager uses sophisticated algorithms to select the best account:
- Capability Filtering: Only accounts with the requested model
- Subscription Tier Priority: ULTRA → PRO → FREE
- Quota-Based Sorting: Higher remaining quota preferred
- Health Score: Accounts with better success rates
- Reset Time: Recently refreshed quotas prioritized
// From src-tauri/src/proxy/token_manager.rs:1055
tokens_snapshot.sort_by(|a, b| {
// Priority 0: Subscription tier
let tier_cmp = tier_priority(&a.subscription_tier)
.cmp(&tier_priority(&b.subscription_tier));
if tier_cmp != std::cmp::Ordering::Equal {
return tier_cmp;
}
// Priority 1: Model quota
let quota_cmp = quota_b.cmp("a_a);
if quota_cmp != std::cmp::Ordering::Equal {
return quota_cmp;
}
// Priority 2: Health score
// Priority 3: Reset time
});
Automatic Token Refresh
Tokens are automatically refreshed before expiration:
// From src-tauri/src/proxy/token_manager.rs:1200
let now = chrono::Utc::now().timestamp();
if now >= token.timestamp - 300 { // 5 minutes before expiry
match oauth::refresh_access_token(&token.refresh_token, Some(&token.account_id)).await {
Ok(token_response) => {
token.access_token = token_response.access_token.clone();
token.expires_in = token_response.expires_in;
token.timestamp = now + token_response.expires_in;
}
}
}
Request Routing
The proxy routes requests through multiple handlers:
// From src-tauri/src/proxy/server.rs:372
let proxy_routes = Router::new()
.route("/health", get(health_check_handler))
// OpenAI Protocol
.route("/v1/models", get(handlers::openai::handle_list_models))
.route("/v1/chat/completions", post(handlers::openai::handle_chat_completions))
.route("/v1/completions", post(handlers::openai::handle_completions))
.route("/v1/images/generations", post(handlers::openai::handle_images_generations))
// Claude Protocol
.route("/v1/messages", post(handlers::claude::handle_messages))
.route("/v1/messages/count_tokens", post(handlers::claude::handle_count_tokens))
// Gemini Protocol
.route("/v1beta/models", get(handlers::gemini::handle_list_models))
.route("/v1beta/models/:model", post(handlers::gemini::handle_generate));
Error Handling
Automatic retry on rate limits and token expiration:
429 Rate Limit
401 Expired Token
// Automatically rotate to next available account
if status_code == 429 {
self.rate_limit_tracker.record(
&account_id,
Some(&normalized_target),
cooldown_seconds
);
// Retry with different account
}
// Trigger automatic token refresh
if status_code == 401 {
let refreshed = refresh_access_token(&token.refresh_token).await?;
// Retry request with new token
}
Integration Examples
Claude Code CLI
export ANTHROPIC_API_KEY="sk-antigravity"
export ANTHROPIC_BASE_URL="http://127.0.0.1:8045"
claude
OpenCode
Use the built-in sync feature:
Open API Proxy Page
Navigate to API Proxy → External Providers
Click OpenCode Sync
Click the Sync button on the OpenCode card
Verify Configuration
Configuration is automatically written to ~/.config/opencode/opencode.json
# Verify connection
opencode run "test" --model antigravity-manager/claude-sonnet-4-5-thinking
Cherry Studio
- Open Settings → Models
- Add new provider:
- Base URL:
http://127.0.0.1:8045/v1
- API Key:
sk-antigravity
- Select available models from the list
Monitoring
Proxy Status
Check current proxy status:
interface ProxyStatus {
running: boolean;
port: number;
base_url: string;
active_accounts: number;
}
Session Bindings
Clear sticky session bindings:
// From src-tauri/src/commands/mod.rs
pub async fn clear_proxy_session_bindings() -> Result<(), String> {
invoke('clear_proxy_session_bindings')
}
Session bindings are automatically cleared when switching accounts.
Advanced Configuration