/api/drd/local/search
GETSearches the local replica of the Distributed Resource Directory. Pure local SQL — no RAIDA round-trip, so results are instant once the replica has synced. All parameters are optional and combine with AND. The local replica may lag the live directory; use /api/drd/user/get for the authoritative per-record read.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
first_name |
string | No | Case-insensitive prefix match on first name. |
last_name |
string | No | Case-insensitive prefix match on last name. |
name |
string | No | Prefix match against first or last name (convenience filter). |
description |
string | No | Case-insensitive substring match against the decoded profile description text (not base64). |
class |
integer | No | Exact denomination code of the record's coin (-8 to 6). |
class_min / class_max |
integer | No | Denomination range (-8 to 6). |
symbol |
integer | No | 0–255; matches either symbol slot. May be given twice (symbol=7&symbol=42) so the record must show both values (either slot order). symbol_b is an accepted alias for the second value. |
symbol1 / symbol2 |
integer | No | Slot-exact first / second avatar symbol (0–255). |
class_rejection |
integer | No | Exact class-rejection code (-8 to 6). |
class_rejection_min / class_rejection_max |
integer | No | Class-rejection range (-8 to 6). |
fee_min / fee_max |
string | No | Inbox fee range as decimal CC strings (same rules as /api/drd/user/post fee). |
sn |
integer | No | Exact serial number. |
sn_min / sn_max |
integer | No | Serial-number range. |
created_after / created_before |
integer | No | Unix seconds filter on created_at. |
updated_after / updated_before |
integer | No | Unix seconds filter on updated_at. |
include_deleted |
boolean | No | Include tombstoned records. Default false. |
sort |
string | No | name (default), created_at, updated_at, fee, or class. |
order |
string | No | asc or desc. |
limit |
integer | No | Page size. Default 50, max 500. |
offset |
integer | No | Paging offset. Default 0. |
Responses
Success Response (200)
Returns a page of matching users plus the total match count. Each user object uses the same fields as /api/drd/user/get (including websafe-base64 description), plus deleted and a formatted QMail address (null when the denomination is not a QMail class 0–4).
{
"command": "drd-local-search",
"success": true,
"count": 1,
"total": 1,
"users": [
{
"denomination": 1,
"serial_number": 9840,
"inbox_fee": "0.5",
"inbox_fee_units": 50000000,
"first_symbol": 3,
"second_symbol": 14,
"class_rejection": 0,
"created_at": 1783741315,
"updated_at": 1783741315,
"account_age_seconds": 86400,
"first_name": "Alice",
"last_name": "Example",
"description": "Q2xvdWRDb2luIGRldmVsb3Blcg",
"deleted": false,
"address": "38.112@byte"
}
]
}
count is the number of rows in this page; total is the full match count for the filter (for paging UI). address is built only when denomination is 0–4 and the serial fits three bytes; otherwise it is JSON null.
Error Responses
400 Bad Request
Invalid filter value (out-of-range class/symbol, bad fee decimal, unknown sort/order, non-numeric timestamp, etc.).
{
"error": true,
"message": "Invalid sort (name|created_at|updated_at|fee|class)",
"code": 400
}
503 Service Unavailable
The local replica store is not open (not initialized).
{
"error": true,
"message": "Local DRD replica not initialized",
"code": 503
}
Examples
cURL Example
curl -X GET "http://localhost:8080/api/drd/local/search?name=Ali&limit=10&sort=name&order=asc"
JavaScript Example
const params = new URLSearchParams({
name: 'Ali',
limit: 10,
sort: 'updated_at',
order: 'desc'
});
fetch(`http://localhost:8080/api/drd/local/search?${params}`)
.then(r => r.json())
.then(data => {
if (data.success) {
console.log(`${data.count} of ${data.total} matches`);
data.users.forEach(u =>
console.log(`${u.first_name} ${u.last_name} — ${u.address ?? 'no QMail address'}`));
} else if (data.code === 503) {
console.log('Replica not ready — call /api/drd/local/sync first');
}
});
Python Example
import requests
url = 'http://localhost:8080/api/drd/local/search'
data = requests.get(url, params={
'name': 'Ali', 'limit': 10, 'sort': 'name', 'order': 'asc'
}).json()
if data.get('success'):
for u in data.get('users', []):
print(f"{u['first_name']} {u['last_name']}: {u.get('address')}")
elif data.get('code') == 503:
print('Local DRD replica not initialized')
Notes
- This endpoint never fans out to RAIDA; it only reads the local store. Kick a sync with
/api/drd/local/syncand check health with/api/drd/local/status. - The local replica may lag the live directory. For a single authoritative record, call
/api/drd/user/get. - Response
descriptionis websafe base64 of the stored UTF-8 text (same as live get/search); thedescriptionquery param is plain text for substring match. - An empty match set is still 200 with
count: 0andtotal: 0.
Related Endpoints
- /api/drd/local/sync - Download / refresh the local replica
- /api/drd/local/status - Replica health and shard cursors
- /api/drd/user/get - Authoritative live per-record read
- /api/drd/user/search - Live RAIDA name search