Create Your Own Module
Build a custom module to connect any tool or service to Rawtoh.
A module is any program that connects to Rawtoh via WebSocket. It can emit events (things that happen) and receive action calls (things to do). If you can write a script that opens a WebSocket, you can build a module.
How a module works
Your module connects to Rawtoh's WebSocket server and communicates using JSON-RPC 2.0. The flow is simple:
- Connect — open a WebSocket to the Rawtoh RPC server
- Register — send your API key to authenticate
- Subscribe — the server tells your module which events it should emit
- Emit events — send data to Rawtoh when something happens
- Receive calls — Rawtoh calls your module when an action needs something done
Step 1: Get an API key
Before your module can connect, you need to register it in Rawtoh:
- Go to Settings → Module Definitions and create a new definition (or use an existing one)
- Go to Settings → Modules and create a new instance
- Copy the API key — it's shown only once
Step 2: Connect and register
Open a WebSocket connection to the Rawtoh RPC server. Within 5 seconds, send a registration request:
// → Send to server
{
"jsonrpc": "2.0",
"id": 1,
"method": "session.register",
"params": { "token": "rth_your_api_key_here" }
}
// ← Server responds
{ "jsonrpc": "2.0", "id": 1, "result": true }If the key is invalid, the server returns an error and closes the connection. If you don't register within 5 seconds, the connection is also closed.
Step 3: Handle subscribe calls
Right after registration, the server tells your module which events it needs. For each event, it sends a request like this:
// ← Server asks your module to subscribe to an event
{
"jsonrpc": "2.0",
"id": 2,
"method": "event.subscribe",
"params": ["chat.message"]
}
// → Your module responds with a subscription ID (any unique string)
{
"jsonrpc": "2.0",
"id": 2,
"result": "sub_abc123"
}Rules:
- Return a unique string as the subscription ID — you'll use it later to emit events
- Return
nullif you don't recognize the event name — never return an error - The server may also call
event.unsubscribewhen an event is no longer needed
Step 4: Emit events
When something happens (a chat message, a button click, a sensor reading — anything), send a notification to the server. Notifications have no id field — they're fire-and-forget.
// → Send to server (notification — no "id" field)
{
"jsonrpc": "2.0",
"method": "event.subscription",
"params": {
"subscription": "sub_abc123",
"result": {
"user": "alice",
"message": "hello world"
}
}
}subscription— the ID you generated duringevent.subscriberesult— the event payload. Any JSON. This becomesevent.payloadin triggers and actions.
Events are rate limited to 10 per second per connection. If you exceed this, the event is dropped.
Step 5: Expose methods (optional)
If you want actions to be able to call your module (e.g. module("my-tool").request("do.something", params)), your module needs to handle incoming JSON-RPC requests:
// ← Server sends a request to your module
{
"jsonrpc": "2.0",
"id": 42,
"method": "lights.set_color",
"params": { "color": "#ff0000" }
}
// → Your module responds
{
"jsonrpc": "2.0",
"id": 42,
"result": { "status": "ok" }
}You define the method names and params — it's your API. Users will be able to call them from action scripts.
Required methods
Your module must handle these 3 methods from the server:
| Method | What you return | Purpose |
|---|---|---|
ping | "pong" | Heartbeat check |
event.subscribe | subscription ID or null | Start emitting an event |
event.unsubscribe | true | Stop emitting an event |
The manifest
To make your module's events and methods appear in Rawtoh's script editor (autocomplete, documentation), you can provide a manifest — a JSON document that describes what your module can do. Set it on the module definition in Settings → Module Definitions.
{
"events": [
{
"name": "sensor.temperature",
"summary": "Temperature reading from sensor"
}
],
"methods": [
{
"name": "lights.set_color",
"summary": "Set the light color",
"params": [
{ "name": "color", "schema": { "type": "string" } }
]
}
]
}The manifest is optional — your module will work without it. But it makes the experience much better for anyone writing automations.
Reconnection
Your module should reconnect automatically when the connection drops. But check the close code first:
| Close code | What to do |
|---|---|
4000 | Don't reconnect. The user disconnected the module on purpose. |
4001 | Don't reconnect. The API key was refreshed — the current one is invalid. |
| Anything else | Reconnect with exponential backoff: 1s → 2s → 4s → 8s → … up to 64s. Reset on successful registration. |
After reconnecting, the server starts a fresh subscribe phase. Discard any old subscription IDs.
Naming convention
All event and method names use dot notation:
- Events:
sensor.temperature,door.opened,game.score_changed - Methods:
lights.set_color,display.show_text,motor.move
Summary
To build a module, your program needs to:
- Open a WebSocket to the Rawtoh RPC server
- Call
session.registerwithin 5 seconds - Handle
ping,event.subscribe, andevent.unsubscribe - Emit events via
event.subscriptionnotifications - Optionally handle custom method calls from actions
- Reconnect on disconnect (respecting close codes)
That's it. Your module can be written in any language — JavaScript, Python, Rust, Go — anything that supports WebSocket and JSON.