/api/drd/server/get
GETReads server descriptors published with /api/drd/server/post. With no parameters it lists every registered server of every role. Narrow it with role, or fetch exactly one server by its identity coin, or one RAIDA by slot number. The core queries all 25 RAIDAs with protocol command 150 server_get and merges the answers. No authentication: the directory is public.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
role |
string | No | raida, qmail, beacon, drd, rke, or all (default). Required when sn or raida_id is given. |
sn |
integer | No | Fetch one server by identity coin serial number. Needs role (not all) and denomination. |
denomination |
integer | With sn |
Denomination of the identity coin (5 = 100,000 CC, 4 = 10,000 CC). |
raida_id |
integer | No | Fetch one RAIDA by slot number 0–24. Needs role=raida. Ignored if sn is also given. |
Responses
Success Response (200)
servers holds the merged descriptors. Which fields appear depends on the role and on what the server chose to publish; optional measured fields (benchmark_ms, network_speed_bps, ram, storage_available, max_object, version) are omitted when the server never reported them. An empty directory is a success with count 0. Fan-out fields are as on every DRD endpoint.
{
"command": "drd-server-get",
"success": true,
"count": 2,
"servers": [
{
"role": "raida",
"denomination": 5,
"serial_number": 17,
"raida_id": 11,
"ip4": "203.0.113.11",
"jurisdiction": "Iceland",
"benchmark_ms": 42,
"network_speed_bps": 1000000000,
"is_a_raida": true,
"created_at": 1788393600,
"updated_at": 1788393600,
"last_seen_at": 1788480000
},
{
"role": "qmail",
"denomination": 5,
"serial_number": 17,
"ip4": "203.0.113.11",
"storage_available": 2000000000000,
"max_object": 1073741824,
"version": 20260905,
"welfare_bytes": 307200,
"min_mailbox_class": 0,
"subscriptions_available": true,
"subscription_url": "https://mail.example.com/subscribe",
"tiers": "100000:0.00010;1000000:0.00008;10000000:0.00006;4294967295:0.00004",
"encryption_types": "4,8",
"accepting_uploads": true,
"is_a_raida": true,
"created_at": 1788393700,
"updated_at": 1788393700,
"last_seen_at": 1788480100
}
],
"pass_count": 25,
"fail_count": 0,
"no_response_count": 0,
"skipped_count": 0,
"quorum": true,
"raida_results": [
{ "raida": 0, "success": true, "status": 250 },
{ "raida": 1, "success": true, "status": 250 }
]
}
| Field | Type | Description |
|---|---|---|
count | integer | Number of descriptors in servers (server-side cap 100 per role per RAIDA). |
servers[].role | string | raida, qmail, beacon, drd, or rke. |
servers[].denomination, serial_number | integer | Identity coin. One machine may appear once per role under the same coin. |
servers[].raida_id | integer | Slot 0–24. RAIDA role only. |
servers[].ip4, ip6 | string | Addresses to dial. At least one is always present. |
servers[].jurisdiction, benchmark_ms | string, integer | RAIDA role only. |
servers[].network_speed_bps | integer | Any role, if measured. |
servers[].ram, processor | integer, string | Service roles, if reported. |
servers[].storage_available, max_object, version, tiers, accepting_uploads | mixed | QMail role only. |
servers[].welfare_bytes | integer | Service roles. Always present (0 when none is offered); reported for beacon too but not settable there. |
servers[].min_mailbox_class | integer | Service roles. Minimum sender address-coin denomination code, 0–4 (0 = 1 CC @bit, 4 = 10,000 CC @giga). |
servers[].subscriptions_available, subscription_url, encryption_types | mixed | Service roles. |
servers[].registration_needed | boolean | Beacon role only. |
servers[].is_a_raida | boolean | Always true for RAIDA rows. For service rows, true only when the same 100,000 CC coin also holds a RAIDA slot — computed by the RAIDAs, never self-asserted. |
servers[].created_at, updated_at, last_seen_at | integer | Unix seconds stamped by the RAIDA: first registration, last change to a fact, last successful post (the heartbeat). A stale last_seen_at means the server stopped re-posting. |
Error Responses
400 Bad Request
Unknown role; sn without role and denomination, or sn of 0; raida_id without role=raida or outside 0–24.
{
"error": true,
"message": "sn lookup needs role, denomination and a valid sn",
"code": 400
}
{
"error": true,
"message": "raida_id lookup needs role=raida and raida_id 0-24",
"code": 400
}
404 Not Found
A single-server lookup (sn or raida_id) found nothing and at least one RAIDA explicitly reported no such entry (status 193). A listing never returns 404; an empty directory is count 0.
{
"error": true,
"message": "Server not registered",
"code": 404
}
500 Internal Server Error
The core could not select an HV=2 encryption coin pair, or the fan-out failed outright.
{
"error": true,
"message": "DRD server get failed",
"code": 500
}
Examples
cURL Example
# Every registered server, all roles
curl -X GET "http://localhost:8080/api/drd/server/get"
# All QMail servers
curl -X GET "http://localhost:8080/api/drd/server/get?role=qmail"
# RAIDA slot 11
curl -X GET "http://localhost:8080/api/drd/server/get?role=raida&raida_id=11"
# One server by identity coin
curl -X GET "http://localhost:8080/api/drd/server/get?role=qmail&denomination=5&sn=17"
JavaScript Example
fetch(`http://localhost:8080/api/drd/server/get?role=qmail`)
.then(r => r.json())
.then(data => {
if (!data.success) { console.error(data.message); return; }
const dayAgo = Date.now() / 1000 - 86400;
data.servers
.filter(s => s.accepting_uploads && s.last_seen_at > dayAgo)
.forEach(s => console.log(`${s.ip4 || s.ip6} free=${s.storage_available ?? '?'} enc=${s.encryption_types ?? ''}`));
});
Python Example
import requests, time
url = 'http://localhost:8080/api/drd/server/get'
data = requests.get(url, params={'role': 'raida'}).json()
if data.get('success'):
slots = {s['raida_id']: s for s in data['servers']}
for i in range(25):
s = slots.get(i)
if s is None:
print(f"RAIDA {i:2}: not registered")
else:
age = int(time.time() - s['last_seen_at'])
print(f"RAIDA {i:2}: {s.get('ip4') or s.get('ip6')} {s['jurisdiction']} seen {age}s ago")
else:
print('Error', data.get('code'), data.get('message'))
Notes
- Independent directories. Each RAIDA keeps its own copy of the server tables, so a freshly registered server may be missing from a few. The merged result is the union; treat
pass_countas a confidence measure. - Discovery, not trust. A listing tells a client where to try. Whether a server actually serves that client is decided by the server itself when the client connects.
- Listings can exceed one UDP datagram; the core handles the TCP retry (RAIDA status 218) internally.
- Older RAIDAs without HV=2 group-16 support answer status 219 and show up in
raida_resultsas failures with no descriptors.
Related Endpoints
- /api/drd/server/post - Register this server
- /api/drd/user/get - Read a user (not server) record
- Protocol: 150 server_get - Wire format the core sends to each RAIDA