Public Endpoints
These endpoints are publicly accessible for relay discovery.
List Relays
Retrieve a list of healthy relay servers, optionally sorted by geographic proximity.
Client latitude for geographic sorting (e.g., 40.7128)
Client longitude for geographic sorting (e.g., -74.0060)
Maximum number of relays to return. Default: 10
Request Example
GET /v1/relays?lat=40.7128&lon=-74.0060&limit=3
Response Example
{
"relays": [
{
"id": "relay-us-east-1",
"name": "US East 1",
"url": "wss://relay-us-east-1.fluxer.app",
"region": "us-east",
"latitude": 40.7128,
"longitude": -74.0060,
"capacity": 10000,
"current_connections": 3542,
"healthy": true,
"public_key": "base64_encoded_public_key",
"registered_at": "2026-01-01T00:00:00Z",
"last_seen_at": "2026-03-04T12:00:00Z"
},
{
"id": "relay-us-east-2",
"name": "US East 2",
"url": "wss://relay-us-east-2.fluxer.app",
"region": "us-east",
"latitude": 39.9526,
"longitude": -75.1652,
"capacity": 10000,
"current_connections": 2891,
"healthy": true,
"public_key": "base64_encoded_public_key",
"registered_at": "2026-01-01T00:00:00Z",
"last_seen_at": "2026-03-04T12:00:00Z"
},
{
"id": "relay-us-west-1",
"name": "US West 1",
"url": "wss://relay-us-west-1.fluxer.app",
"region": "us-west",
"latitude": 37.7749,
"longitude": -122.4194,
"capacity": 10000,
"current_connections": 4123,
"healthy": true,
"public_key": "base64_encoded_public_key",
"registered_at": "2026-01-01T00:00:00Z",
"last_seen_at": "2026-03-04T12:00:00Z"
}
],
"count": 3
}
Array of relay server objects
Number of relays returned
When lat and lon are provided, relays are sorted by distance from the client location. Only healthy relays are returned.
Get Relay Status
Retrieve the current status of a specific relay server.
GET /v1/relays/:id/status
Request Example
GET /v1/relays/relay-us-east-1/status
Response Example
{
"id": "relay-us-east-1",
"name": "US East 1",
"url": "wss://relay-us-east-1.fluxer.app",
"region": "us-east",
"healthy": true,
"current_connections": 3542,
"capacity": 10000,
"last_seen_at": "2026-03-04T12:00:00Z"
}
Human-readable relay name
WebSocket URL for connecting to the relay
Geographic region code (e.g., us-east, eu-west)
Whether the relay is currently healthy and accepting connections
Current number of active connections
Maximum number of concurrent connections
ISO 8601 timestamp of last heartbeat or health check
Error Response
{
"error": "Relay not found",
"code": "RELAY_NOT_FOUND"
}
Status: 404 Not Found
Management Endpoints
These endpoints are used by relay servers to register and maintain their presence in the directory.
In production, these endpoints should be restricted to internal network access only.
Register Relay
Register a new relay server in the directory.
Human-readable relay name
WebSocket URL (must start with wss://)
Geographic latitude (-90 to 90)
Geographic longitude (-180 to 180)
Region code (e.g., us-east, eu-west). Default: unknown
Maximum concurrent connections. Default: 1000
Base64-encoded public key for E2EE
Request Example
POST /v1/relays/register
Content-Type: application/json
{
"name": "US East 3",
"url": "wss://relay-us-east-3.fluxer.app",
"latitude": 40.7128,
"longitude": -74.0060,
"region": "us-east",
"capacity": 10000,
"public_key": "base64_encoded_public_key"
}
Response Example
{
"id": "relay-us-east-3-abc123",
"name": "US East 3",
"url": "wss://relay-us-east-3.fluxer.app",
"latitude": 40.7128,
"longitude": -74.0060,
"region": "us-east",
"capacity": 10000,
"current_connections": 0,
"public_key": "base64_encoded_public_key",
"registered_at": "2026-03-04T12:00:00Z",
"last_seen_at": "2026-03-04T12:00:00Z",
"healthy": true,
"failed_checks": 0
}
Status: 201 Created
The relay ID is auto-generated by the directory. Save this ID for subsequent heartbeat and delete operations.
Send Heartbeat
Update the relay’s last_seen_at timestamp to indicate it’s still active.
POST /v1/relays/:id/heartbeat
Relay server ID (from registration response)
Request Example
POST /v1/relays/relay-us-east-1/heartbeat
Response Example
Status: 200 OK
Relay servers should send heartbeats every 15-30 seconds to maintain their active status.
Error Response
{
"error": "Relay not found",
"code": "RELAY_NOT_FOUND"
}
Status: 404 Not Found
Delete Relay
Remove a relay server from the directory.
Request Example
DELETE /v1/relays/relay-us-east-3-abc123
Response Example
Status: 200 OK
Relays are also automatically removed after 10 consecutive failed health checks.
Health Check
Check if the relay directory service is healthy.
Response Example
{
"status": "ok",
"timestamp": "2026-03-04T12:00:00Z"
}
Status: 200 OK
Error Codes
The relay directory uses the following error codes:
The specified relay ID does not exist in the directory
Request validation failed (missing required fields, invalid format)
An unexpected server error occurred
Client Integration Example
Here’s how a client might discover and connect to a relay:
// 1. Get client's location (from browser geolocation API)
const position = await new Promise((resolve) => {
navigator.geolocation.getCurrentPosition(resolve);
});
const lat = position.coords.latitude;
const lon = position.coords.longitude;
// 2. Query relay directory for closest relays
const response = await fetch(
`https://relay-directory.fluxer.app/v1/relays?lat=${lat}&lon=${lon}&limit=3`
);
const data = await response.json();
// 3. Try connecting to relays in order
for (const relay of data.relays) {
try {
const ws = new WebSocket(relay.url);
await waitForConnection(ws);
console.log(`Connected to ${relay.name} in ${relay.region}`);
break;
} catch (err) {
console.warn(`Failed to connect to ${relay.name}, trying next...`);
}
}
Relay Server Integration Example
Here’s how a relay server might register and maintain presence:
const DIRECTORY_URL = 'https://relay-directory.fluxer.app';
const HEARTBEAT_INTERVAL = 30000; // 30 seconds
// 1. Register with directory on startup
const registerResponse = await fetch(`${DIRECTORY_URL}/v1/relays/register`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'My Relay Server',
url: 'wss://my-relay.example.com',
latitude: 40.7128,
longitude: -74.0060,
region: 'us-east',
capacity: 5000,
public_key: myPublicKey,
}),
});
const relay = await registerResponse.json();
const relayId = relay.id;
console.log(`Registered as ${relayId}`);
// 2. Send heartbeats to maintain presence
setInterval(async () => {
try {
await fetch(`${DIRECTORY_URL}/v1/relays/${relayId}/heartbeat`, {
method: 'POST',
});
console.log('Heartbeat sent');
} catch (err) {
console.error('Heartbeat failed:', err);
}
}, HEARTBEAT_INTERVAL);
// 3. Implement health check endpoint
app.get('/_health', (req, res) => {
res.status(200).send('OK');
});
// 4. Deregister on shutdown
process.on('SIGTERM', async () => {
await fetch(`${DIRECTORY_URL}/v1/relays/${relayId}`, {
method: 'DELETE',
});
process.exit(0);
});
Next Steps
Relay Overview
Learn about relay directory architecture
API Reference
Return to API documentation
Deploy a Relay
Deploy your own relay server
Voice Integration
Integrate voice into your application