Interface with your R1 remotely via WebSocket and a REST API
R-API provides a bridge between the R1 device and external applications through:
- OpenAI-compatible REST API for sending commands
- WebSocket server for real-time R1 communication
- R1 Anywhere that runs on the device to connect to the backend
- Plugin system for extensibility and custom functionality
- ✅ OpenAI-compatible API endpoints (
/v1/chat/completions,/v1/models) - ✅ WebSocket server for bidirectional R1 communication
- ✅ R1 Anywhere with React web interface for testing
- ✅ Real-time command forwarding from API to R1 devices
- ✅ Multi-device support (multiple R1s can connect)
- ✅ Health monitoring and status reporting
- ✅ Modular architecture with plugin system
- ✅ Streaming response support
- ✅ Comprehensive debug and analytics tools
- ✅ MCP (Model Context Protocol) integration for extensible tool support
PORT: Server port (default: 5482)DISABLE_PIN: Set totrueto disable PIN code authentication (default: false)
This R-API instance is hosted at https://r1a.boondit.site. All endpoints are available at this base URL.
By default, each R1 device gets a unique 6-digit PIN code that must be used for API authentication. To disable PIN authentication:
DISABLE_PIN=true npm startWhen PIN codes are disabled, API endpoints can be accessed without authentication.
R1 devices are automatically assigned persistent IDs based on their user agent and IP address. Device IDs follow the format: {adjective}-{noun}-{number} (e.g., green-wolf-23, blue-eagle-8).
Note: Certain device IDs used in documentation examples (like red-fox-42) are blacklisted to prevent accidental assignment to real devices.
When PIN codes are enabled (default), include the PIN code in API requests:
curl -X POST https://r1a.boondit.site/device-red-fox-42/v1/chat/completions \
-H "Authorization: Bearer 123456" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Hello R1!"}],
"model": "r1-command"
}'The PIN code is displayed on the R1 device's console when it connects.
POST /device-{deviceId}/v1/chat/completions
Authorization: Bearer {pin-code} # Required unless DISABLE_PIN=true
Content-Type: application/json
{
"model": "r1-command",
"messages": [
{
"role": "user",
"content": "Turn on the lights"
}
],
"temperature": 0.7,
"max_tokens": 150,
"stream": true
}GET /device-{deviceId}/v1/models
Authorization: Bearer {pin-code} # Required unless DISABLE_PIN=trueGET /healthPOST /{deviceId}/magic-cam/start
POST /{deviceId}/magic-cam/stop
POST /{deviceId}/magic-cam/capture
POST /{deviceId}/magic-cam/switch
GET /{deviceId}/magic-cam/statusNote: Camera commands are now device-specific and require authentication. Only the device owner can control their camera.
GET /{deviceId}/mcp/servers
POST /{deviceId}/mcp/servers
GET /{deviceId}/mcp/servers/{serverName}
DELETE /{deviceId}/mcp/servers/{serverName}
POST /{deviceId}/mcp/servers/{serverName}/toggle
GET /{deviceId}/mcp/servers/{serverName}/tools
POST /{deviceId}/mcp/servers/{serverName}/tools/{toolName}/call
GET /{deviceId}/mcp/logs
GET /mcp/templatesimport io from 'socket.io-client';
const socket = io('https://r1a.boondit.site');{
"type": "chat_completion",
"data": {
"message": "Turn on the lights",
"model": "r1-command",
"temperature": 0.7,
"max_tokens": 150
},
"timestamp": "2025-09-23T12:00:00.000Z"
}{
"type": "response",
"data": {
"response": "Lights turned on successfully",
"originalMessage": "Turn on the lights",
"model": "r1-llm",
"timestamp": "2025-09-23T12:00:00.000Z",
"deviceId": "r1-12345"
}
}Extend R-API functionality with plugins:
// plugins/my-plugin.js
module.exports = {
name: 'my-plugin',
version: '1.0.0',
description: 'Custom functionality',
init: function(app, io, sharedState) {
// Add custom endpoints, WebSocket handlers, etc.
app.get('/api/custom', (req, res) => {
res.json({ message: 'Custom endpoint' });
});
}
};See Plugin Documentation for detailed information.
src/
├── routes/
│ ├── openai.js # OpenAI API endpoints
│ ├── magic-cam.js # Camera control endpoints
│ ├── health.js # Health monitoring
│ └── debug.js # Debug & analytics
├── socket/
│ └── socket-handler.js # WebSocket management
├── utils/
│ └── response-utils.js # Response formatting
└── tests/
└── test-api.js # API testing
plugins/ # Plugin directory
creation-react/ # React web interface
docs/ # Documentation
├── backend.md # Backend architecture
└── plugins.md # Plugin system guide
# Build all React UIs and start the server
npm run allThis will:
- Install dependencies for both React apps
- Build the creation-react interface
- Build the r1-control-panel interface
- Start the R-API server
Then visit https://r1a.boondit.site for the secure, device-specific control panel with MCP management.
Note: The control panel now requires device authentication - enter your R1 device ID and PIN to access your device securely.
import openai
# Replace 'your-device-id' and 'your-pin-code' with actual values
client = openai.OpenAI(
base_url="https://r1a.boondit.site/device-your-device-id/v1",
api_key="your-pin-code" # PIN code as API key
)
response = client.chat.completions.create(
model="r1-command",
messages=[
{"role": "user", "content": "Hello R1!"}
],
stream=True
)# Replace 'your-device-id' and '123456' with actual values
curl -X POST https://r1a.boondit.site/device-your-device-id/v1/chat/completions \
-H "Authorization: Bearer 123456" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Status check"}],
"model": "r1-command",
"temperature": 0.7,
"stream": true
}'import io from 'socket.io-client';
const socket = io('http://localhost:5482');
socket.on('connect', () => {
console.log('Connected to R-API');
});
socket.on('response', (data) => {
console.log('Received response:', data);
});npm run devnode src/tests/test-api.js- Create route modules in
src/routes/ - Add WebSocket handlers in
src/socket/ - Update imports in
src/server.js - Test functionality
- Update documentation
- Create plugin file in
plugins/directory - Implement required interface
- Restart server to load plugin
- Test plugin functionality
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ API Clients │────│ R-API Server│────│ R1 Devices │
│ │ │ │ │ │
│ • OpenAI │ │ • Express │ │ • Creation │
│ • Custom │ │ • Socket.IO │ │ • Hardware │
│ • Frontend │ │ • Plugins │ │ • Sensors │
└─────────────┘ └─────────────┘ └─────────────┘
- Express Server: REST API endpoints
- Socket.IO Server: Real-time WebSocket communication
- Plugin System: Extensible functionality
- R1 Anywhere: Device-side web interface
- Debug Tools: Monitoring and analytics
- Request → API Client → Express Routes
- Queue → Pending Requests → WebSocket Broadcast
- Process → R1 Device → Generate Response
- Return → WebSocket → Response Utils → API Client
Test the MCP system without physical R1 hardware using OpenRouter-powered virtual devices:
# Install dependencies
npm install
# Set OpenRouter API key
export OPENROUTER_API_KEY=your_api_key_here
# Run virtual R1 client
npm run virtual-r1 <deviceId> [serverUrl]
# Example
npm run virtual-r1 virtual-r1-test http://localhost:3000# Run automated tests with virtual R1
npm run test-virtual-r1The virtual R1 client simulates a real R1 device, processing MCP tool results and system prompts through OpenRouter's Claude model. Perfect for testing MCP integration without physical hardware.
See Virtual R1 README for detailed setup and usage instructions.
- Backend Architecture - Detailed technical documentation
- Plugin System - Plugin development guide
- MCP Integration - Model Context Protocol setup and usage
- API Reference - Complete API documentation (planned)
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Update documentation
- Submit a pull request
GPL-3.0