Skip to content

API Reference

Bifrost Proxy provides comprehensive REST APIs for both server and client components, enabling programmatic management, monitoring, and integration with external systems.

ComponentDefault AddressDescription
Server APIhttp://localhost:7082Central proxy server management
Client APIhttp://localhost:7383Local client management

All API endpoints are prefixed with /api/v1/. Future breaking changes will use a new version prefix (e.g., /api/v2/).

GET /api/v1/status

The API follows consistent naming conventions:

ElementConventionExample
JSON fieldssnake_casegit_commit, build_time
URL pathskebab-case/cache/entries, /split/apps
Query parameterssnake_case?limit=10&offset=0

Many endpoints return these standard fields:

FieldTypeDescription
statusstringOperation result (healthy, running, created, etc.)
timestringISO 8601 timestamp of response
versionstringSemantic version (e.g., 1.0.0)
git_commitstringShort git commit hash
build_timestringISO 8601 timestamp of build
go_versionstringGo runtime version
platformstringOS/architecture (e.g., linux/amd64)

All error responses follow this format:

{
"error": "Error message describing what went wrong",
"message": "Additional details (optional)",
"code": "ERROR_CODE (optional)"
}
CodeMeaning
200Success
201Created
204No Content (successful deletion)
400Bad Request (invalid input)
401Unauthorized (missing/invalid token)
403Forbidden (CSRF validation failed)
404Not Found
409Conflict (resource already exists)
500Internal Server Error
503Service Unavailable
Terminal window
curl http://localhost:7082/api/v1/health

Response:

{
"status": "healthy",
"time": "2024-01-15T10:00:00Z"
}
Terminal window
curl -H "Authorization: Bearer your-token" \
http://localhost:7082/api/v1/status
Terminal window
curl -X POST \
-H "Authorization: Bearer your-token" \
-H "X-Requested-With: XMLHttpRequest" \
-H "Content-Type: application/json" \
-d '{"name": "my-route", "domains": ["*.example.com"], "backend": "direct"}' \
http://localhost:7082/api/v1/routes
const API_BASE = 'http://localhost:7082';
const TOKEN = 'your-token';
async function getBackends() {
const response = await fetch(`${API_BASE}/api/v1/backends`, {
headers: {
'Authorization': `Bearer ${TOKEN}`,
},
});
return response.json();
}
async function addRoute(route: { name: string; domains: string[]; backend: string }) {
const response = await fetch(`${API_BASE}/api/v1/routes`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
body: JSON.stringify(route),
});
return response.json();
}
import requests
API_BASE = 'http://localhost:7082'
TOKEN = 'your-token'
headers = {
'Authorization': f'Bearer {TOKEN}',
'X-Requested-With': 'XMLHttpRequest',
}
# Get all backends
response = requests.get(f'{API_BASE}/api/v1/backends', headers=headers)
backends = response.json()
# Add a route
route = {
'name': 'my-route',
'domains': ['*.example.com'],
'backend': 'direct',
}
response = requests.post(
f'{API_BASE}/api/v1/routes',
headers=headers,
json=route
)
package main
import (
"bytes"
"encoding/json"
"net/http"
)
const (
apiBase = "http://localhost:7082"
token = "your-token"
)
func main() {
client := &http.Client{}
// Get backends
req, _ := http.NewRequest("GET", apiBase+"/api/v1/backends", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := client.Do(req)
defer resp.Body.Close()
// Add route
route := map[string]interface{}{
"name": "my-route",
"domains": []string{"*.example.com"},
"backend": "direct",
}
body, _ := json.Marshal(route)
req, _ = http.NewRequest("POST", apiBase+"/api/v1/routes", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, _ = client.Do(req)
}

Connect to receive real-time events:

const ws = new WebSocket('ws://localhost:7082/api/v1/ws?token=your-token');
ws.onopen = () => {
console.log('Connected to Bifrost WebSocket');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Event:', data.type, data.data);
};
// Keep alive
setInterval(() => ws.send('ping'), 30000);