Service
labs
Connects to a Nostr relay as a normal client, runs a battery of checks against the specification and returns a JSON report per module. Test events come from throwaway keys, are tagged as test data and are removed again with NIP-09 where the relay honours it.
Request
| Field | Type | Description |
|---|---|---|
relay | string, required | wss://relay.example.com, ws://..., or a bare host (means wss://). Public hosts and the ports listed in /v1/services/labs only. |
modules | array | "quick" and/or "conformance". Each is one result (one report). |
checks | array | Your own selection of check ids from selectable in /v1/services/labs. Produces one result with the key custom. Unknown ids are ignored. |
webhook | string | Optional public https URL that receives the finished reports as a JSON POST. |
Give modules, checks, or both.
# a full module
curl -s "https://api.relayted.de/v1/labs/jobs?wait=25" \
-H "Authorization: Bearer $RELAYTED_KEY" -H "Content-Type: application/json" \
-d '{"relay":"wss://relay.example.com","modules":["quick"]}'
# only the checks you care about
curl -s "https://api.relayted.de/v1/labs/jobs" \
-H "Authorization: Bearer $RELAYTED_KEY" -H "Content-Type: application/json" \
-d '{"relay":"relay.example.com","checks":["tls.certificate","filters.kinds","filters.since_until"]}'
The check ids in the second example are illustrations; take real ids from /v1/services/labs.
Modules and prices
- quick: DNS, WebSocket handshake, TLS certificate and protocol, connect latency by phase, NIP-11 document, publish and OK, query and EOSE, signature integrity, CLOSE, stability with pings, reconnects, latency percentiles, NIP-09 cleanup.
- conformance: NIP-11, plus against a known dataset: EVENT/OK, REQ/EOSE, CLOSE, subscriptions, duplicates, invalid ids and signatures, malformed messages, every filter compared with a reference implementation, replaceable/addressable/ephemeral events, ordering, deletions, and advertised vs observed limits.
- custom: priced per check, and never more than the module(s) that contain the selection.
- dataset: some checks (all filter checks and a few others) need a known set of test events on the relay. For a custom selection this costs a one-time fee per wallet: it is charged with your first job that needs it, as its own result with the key
datasetand"oneTime": true, and never again, also not after you replace your key. If that job delivers nothing, the fee is refunded and due with the next one. In the Conformance module the dataset is included. The quote shows whether the fee applies to you.
Response and report
{
"job": {
"id": "Mx7...", "service": "labs", "target": "relay.example.com", "status": "completed",
"cost": 200, "refunded": 0, "charged": 200,
"results": [
{ "key": "quick", "status": "done", "price": 200, "contentType": "application/json; charset=utf-8",
"url": ".../results/quick" }
]
},
"balance": 49800
}
While a module runs, its result carries a progress text. The report itself (relaylab.report/1) contains a summary and score, every check with its status (pass, fail, warn, skip, info), a message, details, the specification basis, latency percentiles and the advertised-vs-observed table.
Only checks whose basis is required or essential can report fail; deviations from recommendations and conventions are warnings.
Error codes of this service
| Code | When |
|---|---|
bad_relay_url, bad_port, bad_webhook | The relay address, its port or the webhook URL is not acceptable. |
blocked_address, unreachable | The host is private/local, or does not resolve. |
no_output, no_checks | Neither a module nor a selectable check was given. |
relay_busy (429) | This relay was tested too often in the last hour (all customers together). This protects relays from being hammered. |
A module that cannot run is refunded, with error set to unreachable, not_a_relay, write_restricted, timeout or worker_lost. | |
Notes
- Reports are kept for 30 days.
- Quick takes about 20 to 40 seconds, Conformance one to three minutes. Use polling or several
waitrounds for Conformance. - No load testing: publishing is paced, and there are hard caps per relay.
- The same service with a web interface: labs.relayted.de.