Skip to content

Client API Reference

The Bifrost client exposes a REST API for local management, VPN control, debugging, and desktop app integration.

Default Address: http://localhost:7383

Check if the client is healthy and connected to the server.

GET /api/v1/health

Response:

{
"status": "healthy",
"time": "2024-01-15T10:00:00Z"
}
FieldTypeDescription
statusstringhealthy or degraded (if server connection lost)
timestringISO 8601 timestamp

Get client version information.

GET /api/v1/version

Response:

{
"version": "1.0.0",
"git_commit": "abc123",
"build_time": "2024-01-15T10:00:00Z",
"go_version": "go1.22.0",
"platform": "darwin/arm64"
}

Get comprehensive client status.

GET /api/v1/status

Response:

{
"status": "running",
"version": "1.0.0",
"server_connected": true,
"server_address": "bifrost.example.com:7080",
"http_proxy": "127.0.0.1:7380",
"socks5_proxy": "127.0.0.1:7381",
"vpn_enabled": true,
"vpn_status": "connected",
"debug_entries": 150,
"uptime": "2h30m15s",
"bytes_sent": 104857600,
"bytes_received": 209715200,
"active_connections": 12,
"timestamp": "2024-01-15T10:00:00Z"
}

Establish connection to the Bifrost server.

POST /api/v1/connect

Response:

{
"status": "connected"
}

Disconnect from the Bifrost server.

POST /api/v1/disconnect

Response:

{
"status": "disconnected"
}

Get all configured servers.

GET /api/v1/servers

Response:

[
{
"name": "US West",
"address": "us-west.bifrost.example.com:7080",
"protocol": "HTTP",
"is_default": true,
"latency_ms": 45,
"status": "connected"
},
{
"name": "EU Central",
"address": "eu-central.bifrost.example.com:7080",
"protocol": "HTTP",
"is_default": false,
"latency_ms": 120,
"status": "online"
}
]

Select a server to connect to.

POST /api/v1/server/select

Request Body:

{
"server": "EU Central"
}

Response:

{
"status": "selected",
"server": "EU Central"
}

Get quick settings for desktop app integration.

GET /api/v1/settings

Response:

{
"auto_connect": true,
"start_minimized": false,
"show_notifications": true,
"vpn_enabled": false,
"system_proxy_enabled": true,
"current_server": "US West"
}

Update quick settings.

POST /api/v1/settings

Request Body:

{
"auto_connect": true,
"start_minimized": true,
"show_notifications": true,
"vpn_enabled": true,
"system_proxy_enabled": true,
"current_server": "US West"
}

Response:

{
"status": "updated"
}

Get current client configuration.

GET /api/v1/config

Response: Full ClientConfig object.


Update configuration with partial updates.

PUT /api/v1/config

Request Body:

{
"proxy": {
"http": {
"listen": ":7380"
}
},
"routing": {
"default_action": "server"
}
}

Response:

{
"status": "updated",
"restart_required": true,
"restart_fields": ["proxy.http.listen"],
"warnings": []
}

Restart-Required Fields:

  • proxy.http.listen
  • proxy.socks5.listen
  • web_ui.listen
  • api.listen
  • vpn.enabled
  • vpn.tun
  • mesh.enabled
  • mesh.device

Reload configuration from file.

POST /api/v1/config/reload

Response:

{
"status": "reloaded"
}

Validate configuration changes without applying.

POST /api/v1/config/validate

Request Body: Partial config updates

Response:

{
"valid": true,
"errors": [],
"warnings": ["Changes to proxy.http.listen require client restart"]
}

Get default configuration values.

GET /api/v1/config/defaults

Export configuration to YAML or JSON.

POST /api/v1/config/export?format=yaml
POST /api/v1/config/export?format=json

Response: File download with Content-Disposition: attachment


Import configuration from YAML or JSON.

POST /api/v1/config/import?format=yaml
POST /api/v1/config/import?format=json

Request Body: YAML or JSON configuration

Response:

{
"status": "imported",
"restart_required": false,
"restart_fields": [],
"warnings": []
}

Get all configured routing rules.

GET /api/v1/routes

Response:

[
{
"name": "direct-local",
"patterns": ["*.local", "localhost", "127.0.0.1"],
"action": "direct",
"priority": 100
},
{
"name": "default",
"patterns": ["*"],
"action": "server",
"priority": 0
}
]

Add a new routing rule.

POST /api/v1/routes

Request Body:

{
"name": "work-vpn",
"domains": ["*.company.com", "intranet.*"],
"action": "server",
"priority": 90
}

Response:

{
"status": "created",
"route": "work-vpn",
"domains": ["*.company.com", "intranet.*"],
"action": "server"
}

Remove a routing rule.

DELETE /api/v1/routes/{name}

Response:

{
"status": "removed",
"route": "work-vpn"
}

Test which action a domain would receive.

GET /api/v1/routes/test?domain=api.company.com

Response:

{
"domain": "api.company.com",
"action": "server"
}

Get current VPN connection status.

GET /api/v1/vpn/status

Response:

{
"status": "connected",
"enabled": true,
"tunnel_type": "WireGuard",
"interface_name": "bifrost0",
"ip": "10.0.0.2",
"gateway": "10.0.0.1",
"dns": ["1.1.1.1", "8.8.8.8"],
"mtu": 1420,
"port": 51820,
"encryption": "ChaCha20-Poly1305",
"bytes_sent": 1048576,
"bytes_received": 2097152,
"connected_at": "2024-01-15T10:00:00Z"
}

Status Values:

  • disabled - VPN is not configured
  • connecting - VPN is establishing connection
  • connected - VPN is active
  • error - VPN encountered an error

Enable and start the VPN connection.

POST /api/v1/vpn/enable

Response:

{
"status": "enabled"
}

Disable and stop the VPN connection.

POST /api/v1/vpn/disable

Response:

{
"status": "disabled"
}

Get active VPN connections.

GET /api/v1/vpn/connections

Response:

[
{
"id": "conn-123",
"remote_addr": "api.example.com:443",
"local_addr": "10.0.0.2:54321",
"protocol": "tcp",
"started_at": "2024-01-15T10:00:00Z",
"bytes_sent": 1024,
"bytes_received": 2048
}
]

Get current split tunneling configuration.

GET /api/v1/vpn/split/rules

Response:

{
"mode": "exclude",
"apps": [
{"name": "Slack", "path": "/Applications/Slack.app"},
{"name": "Zoom", "path": "/Applications/zoom.us.app"}
],
"domains": ["*.local", "localhost", "*.lan"],
"ips": ["192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12"]
}

Mode Values:

  • exclude - Traffic from listed apps/domains/IPs bypasses VPN
  • include - Only traffic from listed apps/domains/IPs uses VPN

Change split tunneling mode.

PUT /api/v1/vpn/split/mode

Request Body:

{
"mode": "exclude"
}

Response:

{
"status": "updated",
"mode": "exclude"
}

Add an application to split tunnel rules.

POST /api/v1/vpn/split/apps

Request Body:

{
"name": "Discord",
"path": "/Applications/Discord.app"
}

Response:

{
"status": "added"
}

Remove an application from split tunnel rules.

DELETE /api/v1/vpn/split/apps/{name}

Response:

{
"status": "removed"
}

Add a domain pattern to split tunnel rules.

POST /api/v1/vpn/split/domains

Request Body:

{
"pattern": "*.internal.company.com"
}

Response:

{
"status": "added"
}

DELETE /api/v1/vpn/split/domains/{pattern}

Add an IP range to split tunnel rules.

POST /api/v1/vpn/split/ips

Request Body:

{
"cidr": "172.16.0.0/12"
}

Response:

{
"status": "added"
}

DELETE /api/v1/vpn/split/ips/{cidr}

Get VPN DNS cache entries.

GET /api/v1/vpn/dns/cache

Get all traffic debug entries.

GET /api/v1/debug/entries

Response:

[
{
"timestamp": "2024-01-15T10:00:00Z",
"method": "GET",
"host": "api.example.com",
"path": "/v1/users",
"status_code": 200,
"duration": "150ms",
"action": "server",
"backend": "wireguard-us",
"bytes_sent": 1024,
"bytes_recv": 2048,
"error": ""
}
]

Get the most recent debug entries.

GET /api/v1/debug/entries/last/{count}

Clear all debug entries.

DELETE /api/v1/debug/entries

Response:

{
"message": "cleared"
}

Get only entries with errors.

GET /api/v1/debug/errors

Get memory usage statistics and runtime information.

GET /api/v1/debug/memory

Response:

{
"heap_alloc": 10485760,
"heap_sys": 20971520,
"heap_idle": 5242880,
"heap_inuse": 15728640,
"heap_released": 1048576,
"heap_objects": 50000,
"stack_inuse": 1048576,
"stack_sys": 2097152,
"num_gc": 25,
"last_gc_pause_ns": 500000,
"total_gc_pause_ns": 10000000,
"gc_cpu_fraction": 0.01,
"num_goroutines": 50,
"log_subscribers": 2
}

Get log entries with pagination.

GET /api/v1/logs
GET /api/v1/logs?limit=100&offset=0&level=error

Query Parameters:

ParameterTypeDefaultDescription
limitint100Maximum entries
offsetint0Skip entries
levelstring-Filter by level (info, error, warn, debug)

Response:

{
"entries": [
{
"timestamp": "2024-01-15T10:00:00Z",
"level": "info",
"message": "GET https://api.example.com/v1/users",
"fields": {
"method": "GET",
"url": "api.example.com/v1/users",
"status_code": 200,
"duration_ms": 150,
"action": "server"
}
}
],
"total": 1500,
"limit": 100,
"offset": 0
}

Stream logs in real-time using Server-Sent Events.

GET /api/v1/logs/stream

Response: text/event-stream

data: {"type": "connected"}
data: {"timestamp": "2024-01-15T10:00:00Z", "level": "info", "message": "GET https://api.example.com/v1/users"}
data: {"timestamp": "2024-01-15T10:00:01Z", "level": "error", "message": "Connection failed", "fields": {"error": "timeout"}}

JavaScript Example:

const eventSource = new EventSource('/api/v1/logs/stream');
eventSource.onmessage = (event) => {
const log = JSON.parse(event.data);
console.log(`[${log.level}] ${log.message}`);
};
eventSource.onerror = () => {
console.log('Connection lost, reconnecting...');
};

Get cache statistics.

GET /api/v1/cache/stats

Response:

{
"enabled": true,
"storage_type": "memory",
"hit_rate": 0.75,
"total_requests": 5000,
"cache_hits": 3750,
"cache_misses": 1250,
"entries": 500,
"size_bytes": 52428800,
"max_size_bytes": 104857600
}

Get cached entries.

GET /api/v1/cache/entries?limit=100&offset=0&domain=example.com

Delete a specific cache entry.

DELETE /api/v1/cache/entries/{key}

Clear all cache entries.

POST /api/v1/cache/clear

Response:

{
"status": "cleared"
}

Get mesh network status.

GET /api/v1/mesh/status

Response:

{
"status": "running",
"enabled": true,
"peer_id": "peer-abc123",
"virtual_ip": "10.100.0.2",
"network_id": "net-xyz789",
"network_cidr": "10.100.0.0/24",
"peer_name": "laptop-work",
"peer_count": 5,
"connected_peers": 3,
"direct_connections": 2,
"relayed_connections": 1,
"bytes_sent": 10485760,
"bytes_received": 20971520,
"packets_sent": 10000,
"packets_received": 15000,
"uptime": "2h30m15s"
}

Get detailed mesh statistics.

GET /api/v1/mesh/stats

Enable mesh networking.

POST /api/v1/mesh/enable

Response:

{
"status": "enabled"
}

Disable mesh networking.

POST /api/v1/mesh/disable

Response:

{
"status": "disabled"
}

Get all known peers in the mesh.

GET /api/v1/mesh/peers

Response:

[
{
"id": "peer-xyz789",
"name": "desktop-home",
"virtual_ip": "10.100.0.3",
"virtual_mac": "02:00:00:00:00:03",
"public_key": "base64...",
"status": "connected",
"connection_type": "direct",
"latency_ms": 5,
"last_seen": "2024-01-15T10:00:00Z",
"joined_at": "2024-01-01T00:00:00Z",
"bytes_sent": 1048576,
"bytes_received": 2097152,
"endpoints": [
{
"address": "192.168.1.50",
"port": 51820,
"type": "lan",
"priority": 100
}
],
"metadata": {
"os": "linux",
"version": "1.0.0"
}
}
]

Get only currently connected peers.

GET /api/v1/mesh/peers/connected

Get details of a specific peer.

GET /api/v1/mesh/peers/{id}

Get mesh routing table.

GET /api/v1/mesh/routes

Response:

[
{
"dest_peer_id": "peer-xyz789",
"dest_ip": "10.100.0.3",
"next_hop": "",
"type": "direct",
"metric": 1,
"latency_ms": 5,
"hop_count": 1,
"last_updated": "2024-01-15T10:00:00Z",
"active": true
},
{
"dest_peer_id": "peer-abc456",
"dest_ip": "10.100.0.4",
"next_hop": "peer-xyz789",
"type": "relayed",
"metric": 2,
"latency_ms": 25,
"hop_count": 2,
"last_updated": "2024-01-15T09:55:00Z",
"active": true
}
]

Get mesh network information.

GET /api/v1/mesh/network

Response:

{
"network_id": "net-xyz789",
"network_cidr": "10.100.0.0/24",
"peer_name": "laptop-work",
"local_peer_id": "peer-abc123",
"virtual_ip": "10.100.0.2"
}

The client exposes Go’s pprof endpoints for debugging and profiling.

EndpointDescription
GET /debug/pprof/Profiling index page
GET /debug/pprof/cmdlineCommand line arguments
GET /debug/pprof/profileCPU profile (30s default)
GET /debug/pprof/heapHeap memory profile
GET /debug/pprof/goroutineGoroutine stack traces
GET /debug/pprof/allocsMemory allocation profile
GET /debug/pprof/blockBlock contention profile
GET /debug/pprof/mutexMutex contention profile
GET /debug/pprof/threadcreateThread creation profile
Terminal window
# Get CPU profile (30 seconds)
curl http://localhost:7383/debug/pprof/profile > cpu.prof
# Get heap profile
curl http://localhost:7383/debug/pprof/heap > heap.prof
# Analyze with go tool
go tool pprof cpu.prof