2026-02-17 12:22:36 +00:00

765 lines
19 KiB
JSON

{
"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"]
}
}
}
}