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

  1. Diode Collab is running on the machine (process name is typically dDrive; builds from source may show as beam).
  2. 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.
  3. Shell tools commonly used for discovery: ss, grep, awk, lsof, and — if you use the TLS-to-plain-HTTP pattern below — socat, openssl, and curl.

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:

  1. Connect with a TLS stack that supports the above, or
  2. 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:

  1. 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 ..
  1. 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 &
  1. 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
  1. If the probe succeeds, that $PORT is the Collab API port. Keep the proxy running (or reconnect later the same way) and use 8080 (or your chosen fixed port) for clients.
  2. If the probe fails, kill that socat and 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.