Connect
Connect links dash.uebliche.net to in-game servers. The API stores pending commands, publishes settings updates, and keeps per-server membership data.
Authentication
Server auth (Connect mod/plugin)
Connect servers authenticate with:
Authorization: Bearer <CONNECT_SERVER_SECRET>X-Server-Id: <CONNECT_SERVER_ID>
Servers can request credentials via the registration endpoint and persist them locally (for example in connect.json).
Dashboard auth
Dash uses the API JWT in the Authorization: Bearer <token> header.
Permissions
Dash requests are gated by these permission nodes:
connect:commands:readconnect:commands:writeconnect:settings:readconnect:settings:writeconnect:members:readconnect:members:writeuebliche.connect.extensions.<extensionId>(extension actions)
Endpoints
Networks
Dash creates shared networks for Connect servers. Servers are claimed first via single-use keys, then assigned to a network in Dash. There are no fixed network keys.
List networks
GET /v1/connect/networks
Response:
{
"items": [
{
"id": "object-id",
"networkId": "uuid",
"name": "My Network",
"ownerId": "user-uuid",
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
]
}Create network
POST /v1/connect/networks
{
"name": "My Network"
}Response:
{
"network": {
"id": "object-id",
"networkId": "uuid",
"name": "My Network",
"ownerId": "user-uuid",
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
}Create network join token
POST /v1/connect/networks/{networkId}/join-token
Response:
{
"joinToken": "jwt",
"expiresIn": 900,
"networkId": "uuid"
}The join token is single-use and already embeds the network ID. It is consumed by POST /v1/connect/networks/join.
Join network (single-use token)
POST /v1/connect/networks/join
{
"joinToken": "jwt",
"name": "host-eu-1"
}Response:
{
"serverId": "uuid",
"serverSecret": "uuid",
"networkId": "uuid",
"serverType": "agent",
"name": "host-eu-1"
}Domains (TXT claim)
Networks can claim domains with a TXT record. Create a claim to get the TXT value, add it to DNS, then verify.
List domains
GET /v1/connect/networks/{networkId}/domains
Response:
{
"items": [
{
"id": "object-id",
"networkId": "uuid",
"domain": "example.com",
"token": "token",
"verified": false,
"verifiedAt": null,
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
]
}Create domain claim
POST /v1/connect/networks/{networkId}/domains
{
"domain": "example.com"
}Response:
{
"domain": {
"id": "object-id",
"networkId": "uuid",
"domain": "example.com",
"token": "token",
"verified": false,
"verifiedAt": null,
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
},
"txt": {
"name": "_uebliche.example.com",
"value": "uebliche-network=token"
},
"gateway": {
"type": "CNAME",
"name": "example.com",
"value": "gateway.uebliche.net",
"autoManaged": true
}
}Verify domain
POST /v1/connect/networks/{networkId}/domains/{domainId}/verify
Response:
{
"domain": {
"id": "object-id",
"networkId": "uuid",
"domain": "example.com",
"token": "token",
"verified": true,
"verifiedAt": "2026-01-15T12:00:00Z",
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
}Cloudflare DNS automation
Connect networks can store a Cloudflare API token + zone and let the API manage DNS records automatically.
Get Cloudflare config
GET /v1/connect/networks/{networkId}/dns/cloudflare
Response:
{
"config": {
"networkId": "uuid",
"provider": "cloudflare",
"zoneId": "cloudflare-zone-id",
"zoneName": "example.com",
"tokenStatus": "active",
"gatewayBaseDomain": "gateway.uebliche.net",
"createdAt": "2026-02-16T12:00:00Z",
"updatedAt": "2026-02-16T12:00:00Z"
}
}If no config exists yet, config is null.
Create or update Cloudflare config
PUT /v1/connect/networks/{networkId}/dns/cloudflare
{
"apiToken": "cf-api-token",
"zoneId": "cloudflare-zone-id"
}The API verifies the token and zone before saving. Stored tokens are encrypted at rest in the API database.
Delete Cloudflare config
DELETE /v1/connect/networks/{networkId}/dns/cloudflare
Response:
{
"removed": true
}Automatic record sync
POST /v1/connect/networks/{networkId}/domainsnow auto-upserts_uebliche.<domain>TXT records when Cloudflare DNS automation is configured.POST /v1/connect/networks/{networkId}/domainsnow also tries to auto-upsert a gatewayCNAME(<domain> -> gateway.uebliche.net) when Cloudflare DNS automation is configured for that zone.PUT /v1/connect/servers/{serverId}/gateway-routenow auto-upsertsArecords forrouteHostto active gateway public IPs when the host belongs to the configured Cloudflare zone.- Gateway heartbeats/admin updates can also auto-manage shared gateway records under
CONNECT_GATEWAY_DNS_BASE_DOMAIN(for examplegateway.uebliche.net,<gatewayId>.gateway.uebliche.net) whenCONNECT_GATEWAY_CLOUDFLARE_ZONE_IDandCONNECT_GATEWAY_CLOUDFLARE_API_TOKENare configured.
Public server listing
Connect networks can be published to the public server list used by the launcher.
Get listing
GET /v1/connect/networks/{networkId}/public-server
Response:
{
"server": {
"id": "object-id",
"address": "play.example.net",
"displayName": "Example Network",
"category": "minigames",
"tags": ["pvp", "events"],
"socialLinks": [],
"hidden": false,
"motd": null,
"pingMs": null,
"playerCount": null,
"playerCapacity": null,
"favoriteCount": 0,
"featured": false,
"discoveryState": "CONNECT",
"discoverySource": "connect-network",
"ownershipState": "OWNED",
"ownershipVerifiedAt": "2026-02-06T12:00:00Z",
"favorite": false
}
}If the network is not published yet, server is null.
Publish or update listing
PUT /v1/connect/networks/{networkId}/public-server
{
"address": "play.example.net",
"displayName": "Example Network",
"category": "minigames",
"tags": ["pvp", "events"]
}Response: same as "Get listing".
Unpublish listing
DELETE /v1/connect/networks/{networkId}/public-server
Response:
{
"ok": true
}Servers
Register server credentials
POST /v1/connect/servers/register
{
"serverType": "paper",
"serverName": "hub-eu-1",
"templateId": "template-server-id",
"tempInstance": true
}Response:
{
"serverId": "uuid",
"serverSecret": "uuid",
"networkId": null,
"claimKey": "single-use-claim-key",
"serverType": "paper",
"serverName": "hub-eu-1",
"networkName": null
}Registering a server always returns a single-use claimKey (valid for about 5 minutes). Dash users claim the server with the key and then assign the server to a network.
Templates are marked in Dash by updating the server:
PATCH /v1/connect/servers/{serverId}
{
"isTemplate": true
}Hosts
Agents registered through network join tokens appear as hosts.
GET /v1/connect/hosts
Response:
{
"items": [
{
"id": "object-id",
"serverId": "uuid",
"networkId": "uuid",
"serverType": "agent",
"name": "host-eu-1",
"ownerId": "user-uuid",
"lastSeenAt": "2026-01-22T09:00:00Z",
"lastSeenIp": "203.0.113.1",
"createdAt": "2026-01-22T09:00:00Z",
"updatedAt": "2026-01-22T09:00:00Z"
}
]
}List claimed servers
GET /v1/connect/servers
Response:
{
"items": [
{
"id": "object-id",
"serverId": "uuid",
"networkId": "uuid-or-null",
"serverType": "paper",
"name": "hub-eu-1",
"ownerId": "user-uuid",
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
]
}Claim server (single-use key)
POST /v1/connect/servers/claim
{
"claimKey": "single-use-key"
}Response:
{
"server": {
"id": "object-id",
"serverId": "uuid",
"networkId": null,
"serverType": "paper",
"name": "hub-eu-1",
"ownerId": "user-uuid",
"createdAt": "2026-01-15T12:00:00Z",
"updatedAt": "2026-01-15T12:00:00Z"
}
}Claim keys are generated by server registration. They are single-use and expire after roughly 5 minutes. If the claim key expires, the server can request a fresh key via the claim-key endpoint.
Request a fresh claim key (server auth)
GET /v1/connect/servers/{serverId}/claim-key
Response (unclaimed server):
{
"claimKey": "single-use-key",
"claimed": false,
"expiresAt": "2026-01-15T12:05:00Z"
}Response (already claimed):
{
"claimKey": null,
"claimed": true,
"expiresAt": null
}Assign a server to a network
PATCH /v1/connect/servers/{serverId}
{
"networkId": "uuid-or-null"
}GET /v1/profile/servers
Returns the list of servers the current account can access, including Connect-registered servers (the id will match the Connect serverId).
Commands
Dash creates commands, servers poll and acknowledge them.
POST /v1/connect/servers/{serverId}/commands
{
"action": "kick",
"payload": {
"player": "playerNameOrUuid",
"reason": "Optional reason"
}
}GET /v1/connect/servers/{serverId}/commands?limit=25
POST /v1/connect/servers/{serverId}/commands/{commandId}/ack
{
"status": "success",
"result": {
"message": "Optional response payload"
}
}Settings
GET /v1/connect/servers/{serverId}/settings?source=<extensionId>
PUT /v1/connect/servers/{serverId}/settings
{
"data": {
"example": true
},
"schema": {
"version": "hub.v1",
"fields": [
{
"key": "debug.enabled",
"label": "Debug enabled",
"type": "bool"
}
]
},
"source": "hub",
"schemaVersion": "v1"
}schema is optional. When present, Dash can render typed inputs for the fields. source scopes settings to an extension. Dash should pass the extension ID. Use source connect with a temp boolean in the payload to flag temporary instances:
{
"data": {
"temp": true
},
"source": "connect"
}GET /v1/connect/servers/{serverId}/settings/history?limit=25&source=<extensionId>
Extensions
Extension catalogs are managed in Dash. Servers publish extension availability per server.
GET /v1/connect/extensions
POST /v1/connect/extensions
{
"extensionId": "hub",
"name": "Hub",
"description": "Lobby and compass controls"
}PUT /v1/connect/extensions/{extensionId}
GET /v1/connect/servers/{serverId}/extensions
PUT /v1/connect/servers/{serverId}/extensions/{extensionId}
{
"name": "Hub",
"description": "Lobby and compass controls",
"actions": [
{
"id": "reload_config",
"label": "Reload config",
"description": "Reload the hub config on the server",
"schema": {
"version": "hub.actions.v1",
"fields": [
{ "key": "broadcast", "label": "Broadcast", "type": "bool" }
]
}
}
]
}Settings stream (WebSocket)
GET /v1/connect/servers/{serverId}/stream
- Servers authenticate via headers.
- Dash can pass the JWT as a query param:
/v1/connect/servers/{serverId}/stream?token=<api-jwt>
Members
GET /v1/connect/servers/{serverId}/members
PUT /v1/connect/servers/{serverId}/members/{userId}
{
"role": "viewer"
}DELETE /v1/connect/servers/{serverId}/members/{userId}