Connecting locally to the Diode Collab API
This guide explains how to find Diode Collab’s local JSON-RPC listener on the same machine and talk to it without going through *.diode.link.
For methods, auth, and request/response shapes, see Remote JSON-RPC API. Those docs typically use a remote host like https://<device_address>.diode.link/.... This page covers the local path: discover Collab’s ephemeral TLS port on localhost, optionally unwrap it to plain HTTP on a fixed port, then call the same endpoints.
| Transport | URL | Auth |
|---|---|---|
| HTTP POST | /api/json_rpc |
Authorization: Bearer <token> |
| WebSocket | /api/json_rpc/ws |
authenticate with params.token |
Why use a local connection?
Use local discovery when your integration:
- Runs on the same host as Diode Collab (bots, cron jobs, systemd services, admin tooling, or a local AI)
- Must work offline / without Diode Network routing to the device
- Wants lower latency and fewer moving parts than
device.diode.link - Needs a stable URL for clients that cannot speak Collab’s local TLS handshake directly
The API surface is the same as in Remote JSON-RPC API. Only the host, port, and TLS termination change.
Prerequisites
- Diode Collab is running on the machine (process name is typically
dDrive; builds from source may show asbeam). - The Remote API is enabled on that instance. In chat:
/sysconfig remote-api enable. Token:/sysconfig generate-token/view-token. See Chat Commands and Remote JSON-RPC API. - Shell tools commonly used for discovery:
ss,grep,awk,lsof, and — if you use the TLS-to-plain-HTTP pattern below —socat,openssl, andcurl.
How Collab exposes the API locally
Diode Collab listens on a non-fixed TCP port bound to 0.0.0.0 (not only 127.0.0.1). That listener speaks TLS with:
- TLS 1.2
- elliptic curve secp256k1
- SNI / server name
local - client certificate authentication (a self-signed device cert is enough for local use)
Because the port changes across restarts, clients must discover it, then either:
- Connect with a TLS stack that supports the above, or
- Proxy that TLS port to a fixed plain-HTTP port (for example
localhost:8080).
After that, use the documented paths:
- HTTP:
http://localhost:8080/api/json_rpc - WebSocket:
ws://localhost:8080/api/json_rpc/ws
(or the discovered TLS port directly if your client handles the handshake).
Discovery algorithm
Step 1 — List candidate ports
Find listening sockets owned by Collab, excluding loopback-only binds:
ss -ltp | grep dDrive | grep -v '127\.0\.0\.1'
For Collab built or run from source (Erlang/OTP), the process name may be beam instead:
ss -ltp | grep beam | grep -v '127\.0\.0\.1'
Parse ports that are bound on 0.0.0.0: (there may be more than one; probe each).
Step 2 — Probe each port through a TLS proxy
For each candidate $PORT:
- Generate a client cert if you do not already have one (one-time):
mkdir -p certs && cd certs
openssl ecparam -name secp256k1 -out secp256k1_params.pem
openssl req -newkey ec:./secp256k1_params.pem -nodes \
-keyout device_certificate.pem -x509 -days 365 \
-out device_certificate.pem -subj '/CN=device'
cd ..
- Start a local plain-HTTP listener that forwards to Collab’s TLS port, for example with
socat+openssl s_client:
# Example: proxy Collab TLS on $PORT → plain HTTP on localhost:8080
# Kill anything already on 8080 first if you reuse that port.
socat -d -d TCP-LISTEN:8080,reuseaddr,fork \
EXEC:"openssl s_client -connect localhost:${PORT} -servername local -tls1_2 -curves secp256k1 -cert ./certs/device_certificate.pem -quiet" \
&>/dev/null &
- Probe the proxied endpoint (success = curl exit status 0 within a short timeout):
curl -s --max-time 3 http://localhost:8080/api/json_rpc/ws
- If the probe succeeds, that
$PORTis the Collab API port. Keep the proxy running (or reconnect later the same way) and use8080(or your chosen fixed port) for clients. - If the probe fails, kill that
socatand try the next candidate port.
Step 3 — Call the API
Same contract as Remote JSON-RPC API.
HTTP ping (via local proxy):
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"jsonrpc":"2.0","method":"ping","params":{},"id":1}' \
http://localhost:8080/api/json_rpc
WebSocket: connect to ws://localhost:8080/api/json_rpc/ws, then send:
{
"jsonrpc": "2.0",
"method": "authenticate",
"params": { "token": "<same_as_bearer_token>" },
"id": 1
}
Until authenticate succeeds, other WebSocket methods return not-authorized (-32001). After that, use send_message, subscribe_channel, get_messages, and the rest as documented.
Pseudocode
function find_and_bind_local_collab_api(proxy_port=8080, cert_path):
candidates = ports from `ss -ltp` where process matches dDrive|beam
and listen address is 0.0.0.0 (not 127.0.0.1-only)
for port in candidates:
free(proxy_port)
start_tls_proxy(listen=proxy_port, target=localhost:port, cert=cert_path,
sni="local", tls12=true, curve=secp256k1)
if http_probe("http://localhost:{proxy_port}/api/json_rpc/ws", timeout=3s):
return port # clients use localhost:proxy_port
stop_tls_proxy()
return not_found # Collab not running or API listener not ready
Retry with backoff if Collab is still starting. The listen port is ephemeral across restarts.