API Examples
MsgTier provides a REST HTTP API for managing nodes and sending messages.
Base URL
http://localhost:9000Replace 9000 with the port configured in your node's web_api field.
Endpoints
GET /api/config
Returns the current node's configuration.
Request:
curl http://localhost:9000/api/configResponse:
{
"id": "1",
"secret": "my-secret",
"listeners": [
"udp://0.0.0.0:6666",
"tcp://0.0.0.0:6667"
],
"peers": [
"udp://127.0.0.1:6668",
"ws://127.0.0.1:6669"
],
"relay_network_whitelist": ["*"],
"relay_all_peer_rpc": true,
"foreign_relay_bps_limit": 1048576,
"web_api": "127.0.0.1:9000",
"scripts": {
"chrome": "open /Applications/Google\\ Chrome.app",
"notify": "echo 'Hello'"
},
"hot_reload": {
"enable": true,
"secret": "optional-hot-reload-secret"
},
"static_config": {
"id": "1",
"secret": "my-secret",
"peers": [
"udp://127.0.0.1:6668",
"ws://127.0.0.1:6669"
],
"listeners": [
"udp://0.0.0.0:6666",
"tcp://0.0.0.0:6667"
],
"web_api": "127.0.0.1:9000"
},
"hot_config": {
"scripts": {
"chrome": "open /Applications/Google\\ Chrome.app",
"notify": "echo 'Hello'"
},
"forwards": null,
"exposes": null,
"hot_reload": {
"enable": true,
"secret": "optional-hot-reload-secret"
}
}
}POST /api/config/hot-reload
Update only the hot-reloadable config layer.
Request:
curl -X POST 'http://localhost:9000/api/config/hot-reload' \
-H 'Content-Type: application/json' \
-d '{
"secret": "optional-hot-reload-secret",
"config": {
"scripts": {
"notify": "echo hot reload"
},
"forwards": {},
"exposes": {},
"hot_reload": {
"enable": true,
"secret": "next-secret"
}
}
}'Static fields such as id, secret, listeners, peers, web_api, and port are rejected by this endpoint.
GET /api/status
Returns real-time connection status and peer information.
Request:
curl http://localhost:9000/api/statusResponse:
{
"status": "ok",
"connections": [
{
"id": "conn_1",
"local_addr": "0.0.0.0:6666",
"remote_addr": "127.0.0.1:6668",
"peer_id": "2",
"state": "Active",
"last_seen": 1625000000,
"quality": 100,
"relay": 0,
"metadata": {},
"latency_ms": 15,
"latency_history": [10, 15, 20],
"packets_sent": 150,
"packets_lost": 0,
"bytes_sent": 10240,
"bytes_received": 8192,
"last_ping_time": 1625000000,
"bandwidth_mbps": 100.0,
"packet_loss_rate": 0
}
],
"peers_count": 2,
"active_connections": 2,
"total_connections": 2,
"node_name": "1",
"listeners": [
"0.0.0.0:6666",
"0.0.0.0:6667"
]
}Response Fields:
| Field | Type | Description |
|---|---|---|
status | String | Overall status ("ok") |
connections | Array | List of all connections |
peers_count | Number | Total unique peers |
active_connections | Number | Number of active connections |
total_connections | Number | Total connections (active + inactive) |
node_name | String | This node's ID |
listeners | Array | All listening addresses |
Connection Fields:
| Field | Type | Description |
|---|---|---|
id | String | Unique connection identifier |
peer_id | String | ID of the connected peer |
state | String | Connection state (Active, Disconnected, etc.) |
local_addr | String | Local address used for this connection |
remote_addr | String | Remote peer's address |
latency_ms | Number | Current latency in milliseconds |
packet_loss_rate | Number | Packet loss rate (0-100) |
bandwidth_mbps | Number | Estimated bandwidth in Mbps |
last_seen | Number | Timestamp of last activity |
quality | Number | Connection quality score |
POST /api/send
Send a message to a target peer. Messages are automatically encrypted using X25519 ECDH shared secrets when available.
Request:
curl -X POST 'http://localhost:9000/api/send' \
-H 'target: 2' \
-H 'kind: script' \
-d 'chrome'Headers:
| Header | Required | Description |
|---|---|---|
target | Yes | Peer ID of the destination |
kind | No | Message type (default: "script", can be "text" or "binary") |
timeout | No | Request timeout in ms (default: 10000) |
Content-Type | No | Request content type (default: application/octet-stream) |
Body:
The request body is the message data (typically a script name for kind="script", or raw content for others).
Success Response (200 OK):
{
"status": "ok",
"output": "Script output here..."
}Timeout Response (504):
{
"error": "Request timed out",
"target": "2"
}Peer Not Found (404):
{
"error": "Target peer not found",
"target": "2"
}Missing Target Header (400):
{
"error": "Missing target header"
}Examples
Example 1: Check Node Status
curl http://localhost:9000/api/status | jq '.connections | length'Output: Number of total connections
Example 2: Send Script Trigger
Trigger the "chrome" script on peer "1":
curl -X POST 'http://localhost:9000/api/send' \
-H 'target: 1' \
-H 'kind: script' \
-d 'chrome'Example 3: Send Custom Message
Send a custom message to a peer:
curl -X POST 'http://localhost:9000/api/send' \
-H 'target: 1' \
-H 'kind: script' \
-d 'hello world'Note: If "hello world" is not a configured script name, the message is received but no script executes.
Example 4: Monitor Connections in Real-Time
# Watch connection status every second
watch -n 1 "curl -s http://localhost:9000/api/status | jq '.active_connections'"Example 5: List All Connected Peers
curl -s http://localhost:9000/api/status | jq '.connections[] | .peer_id' | sort -uExample 6: Check for Inactive Connections
curl -s http://localhost:9000/api/status | jq '.connections[] | select(.active == false)'Example 7: Automated Health Check
#!/bin/bash
while true; do
status=$(curl -s http://localhost:9000/api/status)
active=$(echo "$status" | jq '.active_connections')
total=$(echo "$status" | jq '.total_connections')
echo "$(date): Active: $active / Total: $total"
sleep 5
doneError Handling
Common Errors
400 Bad Request
{
"error": "Missing target header"
}Solution: Add target header with peer ID
404 Not Found
{
"error": "Target peer not found",
"target": "unknown-peer"
}Solution: Verify peer exists - check /api/status endpoint
503 Service Unavailable
{
"error": "No active connection to target"
}Solution: Wait for peer to connect and become active
Message Routing
When you send a message:
- Encryption: If a shared secret with the target peer is available, the message is encrypted using X25519 ECDH
- Direct Route: If target peer has active connections, message is sent directly
- Relay Route: If target has no active connections but is reachable through another peer, message is relayed
- Queued: Message is queued if target isn't currently reachable
- Failed: Returns error if target peer doesn't exist in network
Note: Messages to peers without an established shared secret are sent unencrypted with a warning logged.
Rate Limiting
No rate limiting is currently implemented. Use reasonable request intervals to avoid overwhelming the network.
Best Practices
- Always check /api/status before sending critical messages
- Handle 404 errors gracefully - peer may not have discovered yet
- Use meaningful script names in config for clarity
- Monitor active_connections to detect network issues
- Implement retry logic for failed sends with exponential backoff
Troubleshooting API Issues
Issue: Always getting 404 for valid peers
- Check node discovery logs
- Verify peer addresses in config
- Wait 10+ seconds for peer discovery to complete
Issue: Connections showing as inactive
- Check firewall rules for UDP
- Verify network connectivity
- Review heartbeat logs for pong responses
Issue: Message not triggering script
- Verify script name matches exactly (case-sensitive)
- Check script syntax for your platform
- Review server logs for execution errors