{ "openapi": "3.1.0", "info": { "title": "Fluxer Relay Directory API", "version": "1.0.0", "description": "API for discovering and managing Fluxer relay servers for federation. The relay directory service maintains a registry of available relay servers that clients can use to connect to Fluxer instances through encrypted tunnels.", "contact": { "name": "Fluxer Developers", "email": "developers@fluxer.app" }, "license": { "name": "AGPL-3.0", "url": "https://www.gnu.org/licenses/agpl-3.0.html" } }, "servers": [ { "url": "https://relay.fluxer.app", "description": "Production relay directory" } ], "paths": { "/_health": { "get": { "operationId": "getHealth", "summary": "Health check", "description": "Returns the health status of the relay directory service.", "tags": ["Health"], "responses": { "200": { "description": "Service is healthy", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthCheckResponse" } } } } } } }, "/v1/relays": { "get": { "operationId": "listRelays", "summary": "List available relays", "description": "Returns a list of available relay servers. Optionally, provide client coordinates to sort relays by proximity.", "tags": ["Relays"], "parameters": [ { "name": "lat", "in": "query", "description": "Client latitude for proximity-based sorting", "required": false, "schema": { "type": "string" } }, { "name": "lon", "in": "query", "description": "Client longitude for proximity-based sorting", "required": false, "schema": { "type": "string" } }, { "name": "limit", "in": "query", "description": "Maximum number of relays to return", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of available relays", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayListResponse" } } } } } } }, "/v1/relays/register": { "post": { "operationId": "registerRelay", "summary": "Register a new relay", "description": "Registers a new relay server with the directory. The relay must provide its public key for E2E encryption.", "tags": ["Relays"], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRelayRequest" } } } }, "responses": { "201": { "description": "Relay registered successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayInfoResponse" } } } } } } }, "/v1/relays/{id}/status": { "get": { "operationId": "getRelayStatus", "summary": "Get relay status", "description": "Returns the current status of a specific relay server.", "tags": ["Relays"], "parameters": [ { "name": "id", "in": "path", "description": "Relay UUID", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Relay status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayStatusResponse" } } } }, "404": { "description": "Relay not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayNotFoundError" } } } } } } }, "/v1/relays/{id}/heartbeat": { "post": { "operationId": "sendHeartbeat", "summary": "Send relay heartbeat", "description": "Sends a heartbeat to indicate the relay is still alive. Relays should send heartbeats periodically to maintain their healthy status.", "tags": ["Relays"], "parameters": [ { "name": "id", "in": "path", "description": "Relay UUID", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Heartbeat received", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayHeartbeatResponse" } } } }, "404": { "description": "Relay not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayNotFoundError" } } } } } } }, "/v1/relays/{id}": { "delete": { "operationId": "deleteRelay", "summary": "Unregister a relay", "description": "Removes a relay server from the directory.", "tags": ["Relays"], "parameters": [ { "name": "id", "in": "path", "description": "Relay UUID", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Relay deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayDeletedResponse" } } } }, "404": { "description": "Relay not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RelayNotFoundError" } } } } } } } }, "components": { "schemas": { "HealthCheckResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": ["ok"], "description": "Health status" }, "timestamp": { "type": "string", "format": "date-time", "description": "Current server timestamp" } }, "required": ["status", "timestamp"] }, "RelayInfoResponse": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the relay" }, "name": { "type": "string", "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "latitude": { "type": "number", "description": "Geographic latitude of the relay" }, "longitude": { "type": "number", "description": "Geographic longitude of the relay" }, "region": { "type": "string", "description": "Region identifier (e.g., eu-west, us-east)" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Maximum number of connections this relay can handle" }, "current_connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Current number of active connections" }, "public_key": { "type": "string", "description": "Base64-encoded X25519 public key for E2E encryption" }, "registered_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the relay was registered" }, "last_seen_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of the last health check or heartbeat" }, "healthy": { "type": "boolean", "description": "Whether the relay is currently healthy" } }, "required": [ "id", "name", "url", "latitude", "longitude", "region", "capacity", "current_connections", "public_key", "registered_at", "last_seen_at", "healthy" ] }, "RelayWithDistanceResponse": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the relay" }, "name": { "type": "string", "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "latitude": { "type": "number", "description": "Geographic latitude of the relay" }, "longitude": { "type": "number", "description": "Geographic longitude of the relay" }, "region": { "type": "string", "description": "Region identifier (e.g., eu-west, us-east)" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Maximum number of connections this relay can handle" }, "current_connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Current number of active connections" }, "public_key": { "type": "string", "description": "Base64-encoded X25519 public key for E2E encryption" }, "registered_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the relay was registered" }, "last_seen_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of the last health check or heartbeat" }, "healthy": { "type": "boolean", "description": "Whether the relay is currently healthy" }, "distance_km": { "type": "number", "minimum": 0, "description": "Distance from client location in kilometres" } }, "required": [ "id", "name", "url", "latitude", "longitude", "region", "capacity", "current_connections", "public_key", "registered_at", "last_seen_at", "healthy", "distance_km" ] }, "RelayListResponse": { "type": "object", "properties": { "relays": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the relay" }, "name": { "type": "string", "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "latitude": { "type": "number", "description": "Geographic latitude of the relay" }, "longitude": { "type": "number", "description": "Geographic longitude of the relay" }, "region": { "type": "string", "description": "Region identifier (e.g., eu-west, us-east)" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Maximum number of connections this relay can handle" }, "current_connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Current number of active connections" }, "public_key": { "type": "string", "description": "Base64-encoded X25519 public key for E2E encryption" }, "registered_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the relay was registered" }, "last_seen_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of the last health check or heartbeat" }, "healthy": { "type": "boolean", "description": "Whether the relay is currently healthy" } }, "required": [ "id", "name", "url", "latitude", "longitude", "region", "capacity", "current_connections", "public_key", "registered_at", "last_seen_at", "healthy" ] }, { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the relay" }, "name": { "type": "string", "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "latitude": { "type": "number", "description": "Geographic latitude of the relay" }, "longitude": { "type": "number", "description": "Geographic longitude of the relay" }, "region": { "type": "string", "description": "Region identifier (e.g., eu-west, us-east)" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Maximum number of connections this relay can handle" }, "current_connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Current number of active connections" }, "public_key": { "type": "string", "description": "Base64-encoded X25519 public key for E2E encryption" }, "registered_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp when the relay was registered" }, "last_seen_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of the last health check or heartbeat" }, "healthy": { "type": "boolean", "description": "Whether the relay is currently healthy" }, "distance_km": { "type": "number", "minimum": 0, "description": "Distance from client location in kilometres" } }, "required": [ "id", "name", "url", "latitude", "longitude", "region", "capacity", "current_connections", "public_key", "registered_at", "last_seen_at", "healthy", "distance_km" ] } ] }, "description": "List of available relays" }, "count": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Total number of relays returned" } }, "required": ["relays", "count"] }, "RelayStatusResponse": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the relay" }, "name": { "type": "string", "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "region": { "type": "string", "description": "Region identifier" }, "healthy": { "type": "boolean", "description": "Whether the relay is currently healthy" }, "current_connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Current number of active connections" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "format": "int64", "description": "Maximum connection capacity" }, "last_seen_at": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp of the last health check or heartbeat" } }, "required": ["id", "name", "url", "region", "healthy", "current_connections", "capacity", "last_seen_at"] }, "RelayHeartbeatResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": ["ok"], "description": "Confirmation that heartbeat was received" } }, "required": ["status"] }, "RelayDeletedResponse": { "type": "object", "properties": { "status": { "type": "string", "enum": ["deleted"], "description": "Confirmation that relay was deleted" } }, "required": ["status"] }, "RegisterRelayRequest": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 100, "description": "Human-readable name of the relay" }, "url": { "type": "string", "format": "uri", "description": "Base URL of the relay service" }, "latitude": { "type": "number", "minimum": -90, "maximum": 90, "description": "Geographic latitude of the relay" }, "longitude": { "type": "number", "minimum": -180, "maximum": 180, "description": "Geographic longitude of the relay" }, "region": { "type": "string", "minLength": 1, "maxLength": 50, "description": "Region identifier" }, "capacity": { "type": "integer", "minimum": 1, "maximum": 9007199254740991, "format": "int64", "description": "Maximum connection capacity" }, "public_key": { "type": "string", "minLength": 1, "description": "Base64-encoded X25519 public key for E2E encryption" } }, "required": ["name", "url", "latitude", "longitude", "public_key"] }, "RelayIdParam": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "description": "Relay UUID" } }, "required": ["id"] }, "RelayListQuery": { "type": "object", "properties": { "lat": { "type": "string", "description": "Client latitude for proximity sorting" }, "lon": { "type": "string", "description": "Client longitude for proximity sorting" }, "limit": { "type": "string", "description": "Maximum number of relays to return" } } }, "RelayNotFoundError": { "type": "object", "properties": { "error": { "type": "string", "description": "Error message" }, "code": { "type": "string", "enum": ["RELAY_NOT_FOUND"], "description": "Error code" } }, "required": ["error", "code"] } } } }