Skip to main content

Public Endpoints

These endpoints are publicly accessible for relay discovery.

List Relays

Retrieve a list of healthy relay servers, optionally sorted by geographic proximity.
GET /v1/relays
lat
string
Client latitude for geographic sorting (e.g., 40.7128)
lon
string
Client longitude for geographic sorting (e.g., -74.0060)
limit
string
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
}
relays
array
Array of relay server objects
count
number
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
id
string
required
Relay server ID

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"
}
id
string
Relay server identifier
name
string
Human-readable relay name
url
string
WebSocket URL for connecting to the relay
region
string
Geographic region code (e.g., us-east, eu-west)
healthy
boolean
Whether the relay is currently healthy and accepting connections
current_connections
number
Current number of active connections
capacity
number
Maximum number of concurrent connections
last_seen_at
string
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.
POST /v1/relays/register
name
string
required
Human-readable relay name
url
string
required
WebSocket URL (must start with wss://)
latitude
number
required
Geographic latitude (-90 to 90)
longitude
number
required
Geographic longitude (-180 to 180)
region
string
Region code (e.g., us-east, eu-west). Default: unknown
capacity
number
Maximum concurrent connections. Default: 1000
public_key
string
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
id
string
required
Relay server ID (from registration response)

Request Example

POST /v1/relays/relay-us-east-1/heartbeat

Response Example

{
  "status": "ok"
}
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.
DELETE /v1/relays/:id
id
string
required
Relay server ID

Request Example

DELETE /v1/relays/relay-us-east-3-abc123

Response Example

{
  "status": "deleted"
}
Status: 200 OK
Relays are also automatically removed after 10 consecutive failed health checks.

Health Check

Check if the relay directory service is healthy.
GET /_health

Response Example

{
  "status": "ok",
  "timestamp": "2026-03-04T12:00:00Z"
}
Status: 200 OK

Error Codes

The relay directory uses the following error codes:
RELAY_NOT_FOUND
404
The specified relay ID does not exist in the directory
INVALID_REQUEST
400
Request validation failed (missing required fields, invalid format)
INTERNAL_ERROR
500
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

Build docs developers (and LLMs) love