765 lines
19 KiB
JSON
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"]
|
|
}
|
|
}
|
|
}
|
|
}
|