Your comprehensive guide to the TuyaOpen SDK API — covering every method, parameter, and return value you need to build production-ready IoT applications.
Table of Contents
- Introduction
- Installation & Setup
- Authentication Module
- Device Management API
- Device Control Methods
- MQTT Client API
- Event Handling System
- Token Management
- Error Handling & Debugging
- Advanced Device Operations
- Scene & Automation API
- Webhook Integration
- Performance Optimization
- Security Considerations
- Best Practices
- Conclusion
Introduction
The TuyaOpen SDK API provides a complete TypeScript/JavaScript interface for interacting with the Tuya IoT platform. This tuyaopen reference covers all major classes and methods you'll use when building IoT applications, from simple device control to complex multi-device automation systems.
Whether you're connecting a single smart plug or managing thousands of sensors across multiple locations, this SDK API reference gives you the detailed technical information needed to implement robust, production-grade solutions.
What This Reference Covers:
- Complete method signatures with parameter types
- Return value specifications
- Real-world usage examples
- Error scenarios and handling strategies
- Performance optimization tips
Installation & Setup
Before diving into the API, ensure you have the SDK properly installed:
# Install the core TuyaOpen SDK
npm install @tuya/tuya-iot-sdk @tuya/device-connector
# Install TypeScript types (recommended)
npm install --save-dev @types/node typescript
Basic Configuration
import { TuyaOpenAPI, TuyaMQTTClient } from '@tuya/tuya-iot-sdk';
// Initialize the API client
const api = new TuyaOpenAPI({
accessId: 'your_access_id',
accessSecret: 'your_access_secret',
endpoint: 'https://openapi.tuyacn.com', // Adjust for your region
});
// Authenticate
await api.login();
Authentication Module
TuyaOpenAPI Class
The main entry point for all Tuya IoT platform interactions.
Constructor Options
interface TuyaOpenAPIOptions {
accessId: string; // Your Tuya IoT Platform Access ID
accessSecret: string; // Your Tuya IoT Platform Access Secret
endpoint: string; // API endpoint URL (region-specific)
token?: string; // Optional session token (for reconnection)
timeout?: number; // Request timeout in milliseconds (default: 10000)
}
login() Method
Authenticates with the Tuya IoT platform and obtains a session token.
Signature:
login(): Promise<LoginResponse>
Return Value:
interface LoginResponse {
success: boolean;
token: string; // Session token for subsequent requests
expireTime: number; // Token expiration timestamp (Unix epoch)
uid: string; // User ID
}
Example:
try {
const result = await api.login();
console.log(`Authenticated as user: ${result.uid}`);
console.log(`Token expires at: ${new Date(result.expireTime * 1000)}`);
} catch (error) {
console.error('Authentication failed:', error.message);
}
Error Codes:
| Code | Message | Solution |
|------|---------|----------|
| 1001 | Invalid credentials | Verify accessId and accessSecret |
| 1002 | Token expired | Call login() again |
| 1003 | Network timeout | Check connectivity, increase timeout |
| 1004 | Rate limit exceeded | Implement exponential backoff |
Device Management API
getDevices() Method
Retrieves all devices associated with your Tuya IoT account.
Signature:
getDevices(options?: DeviceQueryOptions): Promise<Device[]>
Parameters:
interface DeviceQueryOptions {
deviceId?: string; // Filter by specific device ID
productId?: string; // Filter by product ID
deviceName?: string; // Filter by device name (partial match)
limit?: number; // Maximum results (default: 100, max: 500)
offset?: number; // Pagination offset (default: 0)
}
Return Value:
interface Device {
id: string; // Unique device ID
name: string; // Device name (user-defined)
productId: string; // Product ID
productCategory: string; // Category code (e.g., 'kg', 'dj', 'wsdcg')
online: boolean; // Current online status
activeTime: number; // Last activity timestamp
createTime: number; // Device registration timestamp
ip: string; // Device IP address (if available)
timezone: string; // Device timezone
status: DeviceStatus[]; // Current device status points
}
interface DeviceStatus {
code: string; // DP code (e.g., 'switch', 'bright_value')
value: any; // Current value
}
Example:
// Get all devices
const allDevices = await api.getDevices();
console.log(`Found ${allDevices.length} devices`);
// Filter by product category
const lights = await api.getDevices({ productId: 'light-product-123' });
// Pagination for large device lists
const firstPage = await api.getDevices({ limit: 100, offset: 0 });
const secondPage = await api.getDevices({ limit: 100, offset: 100 });
getDevice(deviceId) Method
Retrieves detailed information for a specific device.
Signature:
getDevice(deviceId: string): Promise<Device>
Example:
const device = await api.getDevice('ebxxxxxxxxxxxxx');
console.log(`Device ${device.name} is ${device.online ? 'online' : 'offline'}`);
console.log('Current status:', device.status);
Device Control Methods
TuyaDevice Class
Represents a single connected device for real-time control and monitoring.
Constructor
const device = new TuyaDevice({
deviceId: 'ebxxxxxxxxxxxxx',
api: api, // TuyaOpenAPI instance
});
getStatus() Method
Fetches the current status of all data points (DPs) from the device.
Signature:
getStatus(): Promise<Record<string, any>>
Return Value:
{
switch: boolean, // On/off state
bright_value?: number, // Brightness (0-1000)
colour?: { // RGB color (for smart lights)
h: number; // Hue (0-360)
s: number; // Saturation (0-255)
v: number; // Value (0-255)
};
temp_value?: number; // Temperature (for sensors)
humidity?: number; // Humidity percentage
power?: number; // Power consumption (watts)
// ... additional DP codes based on device category
}
Example:
const status = await device.getStatus();
console.log('Switch state:', status.switch);
if (status.colour) {
console.log(`Color: H${status.colour.h} S${status.colour.s} V${status.colour.v}`);
}
sendCommand() Method
Sends control commands to the device.
Signature:
sendCommand(commands: CommandPayload): Promise<void>
Parameters:
type CommandPayload = Record<string, any>;
Example - Smart Plug:
// Turn on
await device.sendCommand({ switch: true });
// Turn off with countdown (5 minutes)
await device.sendCommand({
switch: false,
countdown: 300 // seconds
});
Example - Smart Light:
// Set brightness
await device.sendCommand({ bright_value: 800 });
// Set color (warm white)
await device.sendCommand({
colour: { h: 30, s: 50, v: 255 },
work_mode: 'colour'
});
// Set to white mode with specific temperature
await device.sendCommand({
work_mode: 'white',
temp_value: 400 // 0-1000, lower=warm, higher=cool
});
Example - Temperature Sensor:
// Query current temperature (read-only, for demonstration)
const status = await device.getStatus();
console.log(`Temperature: ${status.temp_value / 10}°C`);
console.log(`Humidity: ${status.humidity}%`);
sendCommands() Method (Batch)
Sends multiple commands in a single request for efficiency.
Signature:
sendCommands(commandList: CommandPayload[]): Promise<void>
Example:
await device.sendCommands([
{ switch: true },
{ bright_value: 600 },
{ countdown: 0 } // Cancel any existing countdown
]);
MQTT Client API
TuyaMQTTClient Class
Provides real-time bidirectional communication with devices via MQTT protocol.
Constructor Options
interface MQTTClientOptions {
accessId: string;
accessSecret: string;
endpoint: string;
protocol?: 'mqtt' | 'mqtts'; // Default: 'mqtts' (secure)
port?: number; // Default: 8883 for mqtts, 1883 for mqtt
clientId?: string; // Auto-generated if not provided
}
connect() Method
Establishes MQTT connection to Tuya's message broker.
Signature:
connect(): Promise<void>
Example:
const mqttClient = new TuyaMQTTClient({
accessId: process.env.TUYA_ACCESS_ID,
accessSecret: process.env.TUYA_ACCESS_SECRET,
endpoint: process.env.TUYA_API_ENDPOINT,
});
try {
await mqttClient.connect();
console.log('✅ MQTT connection established');
} catch (error) {
console.error('MQTT connection failed:', error);
}
getDevice() Method
Retrieves a TuyaDevice instance connected via MQTT for real-time updates.
Signature:
getDevice(deviceId: string): Promise<TuyaDevice>
Example:
const device = await mqttClient.getDevice('ebxxxxxxxxxxxxx');
// Subscribe to real-time updates
device.on('status-update', (status) => {
console.log('Real-time update:', status);
});
disconnect() Method
Gracefully closes the MQTT connection.
Signature:
disconnect(): Promise<void>
Best Practice:
// Always disconnect on application shutdown
process.on('SIGINT', async () => {
await mqttClient.disconnect();
process.exit(0);
});
Event Handling System
The tuyaopen SDK provides a robust event emitter system for monitoring device state changes.
Device Events
status-update Event
Emitted when device status changes (via MQTT subscription).
Signature:
device.on('status-update', (status: Record<string, any>) => void)
Example:
device.on('status-update', (newStatus) => {
if (newStatus.switch === true) {
console.log('Device turned ON');
} else if (newStatus.switch === false) {
console.log('Device turned OFF');
}
// Log power consumption if available
if (newStatus.power !== undefined) {
console.log(`Current power: ${newStatus.power}W`);
}
});
disconnect Event
Emitted when the device loses connection.
Signature:
device.on('disconnect', () => void)
Example:
device.on('disconnect', () => {
console.warn('⚠️ Device disconnected, attempting reconnect...');
// Implement reconnection logic
setTimeout(async () => {
try {
await device.connect();
console.log('✅ Reconnected successfully');
} catch (error) {
console.error('Reconnection failed:', error);
}
}, 5000);
});
error Event
Emitted when an error occurs during device operations.
Signature:
device.on('error', (error: Error) => void)
Example:
device.on('error', (error) => {
console.error('Device error:', error.message, error.code);
// Handle specific error types
if (error.code === 'TOKEN_EXPIRED') {
// Trigger token refresh
refreshToken();
}
});
MQTT Client Events
mqttClient.on('connect', () => {
console.log('MQTT client connected');
});
mqttClient.on('reconnect', () => {
console.log('MQTT client reconnecting...');
});
mqttClient.on('offline', () => {
console.log('MQTT client offline');
});
mqttClient.on('error', (error) => {
console.error('MQTT client error:', error);
});
Token Management
getToken() Method
Retrieves the current session token.
Signature:
getToken(): string
refreshToken() Method
Manually refreshes the authentication token before expiration.
Signature:
refreshToken(): Promise<string>
Return Value: New token string
Example - Automatic Token Refresh:
class TokenManager {
private api: TuyaOpenAPI;
private tokenExpireTime: number;
private refreshBuffer: number = 300000; // 5 minutes before expiration
constructor(api: TuyaOpenAPI) {
this.api = api;
}
async initialize(): Promise<void> {
const result = await this.api.login();
this.tokenExpireTime = result.expireTime * 1000;
this.scheduleRefresh();
}
private scheduleRefresh(): void {
const refreshTime = this.tokenExpireTime - Date.now() - this.refreshBuffer;
if (refreshTime > 0) {
setTimeout(async () => {
try {
const result = await this.api.login();
this.tokenExpireTime = result.expireTime * 1000;
console.log('Token refreshed successfully');
this.scheduleRefresh();
} catch (error) {
console.error('Token refresh failed:', error);
// Retry in 1 minute
setTimeout(() => this.scheduleRefresh(), 60000);
}
}, refreshTime);
}
}
}
// Usage
const tokenManager = new TokenManager(api);
await tokenManager.initialize();
Error Handling & Debugging
Common Error Types
interface TuyaError extends Error {
code: string;
message: string;
details?: any;
}
Error Code Reference
| Error Code | Description | Recommended Action |
|---|---|---|
TOKEN_EXPIRED |
Session token has expired | Call refreshToken()
|
DEVICE_OFFLINE |
Device is not connected | Check device power/network |
INVALID_COMMAND |
Command format is incorrect | Verify DP codes for device |
RATE_LIMIT |
API rate limit exceeded | Implement backoff strategy |
NETWORK_TIMEOUT |
Request timed out | Increase timeout, check network |
PERMISSION_DENIED |
Insufficient permissions | Verify API credentials |
Debug Mode
Enable detailed logging for troubleshooting:
import { setDebugMode } from '@tuya/tuya-iot-sdk';
// Enable debug logging
setDebugMode(true);
// Or with custom logger
setDebugMode(true, {
log: (message) => console.log('[TuyaSDK]', message),
warn: (message) => console.warn('[TuyaSDK]', message),
error: (message) => console.error('[TuyaSDK]', message),
});
Retry Logic Implementation
async function executeWithRetry<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error as Error;
// Don't retry on certain errors
if ((error as TuyaError).code === 'INVALID_COMMAND') {
throw error;
}
if (attempt < maxRetries) {
const delay = baseDelay * Math.pow(2, attempt - 1); // Exponential backoff
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError!;
}
// Usage
const status = await executeWithRetry(() => device.getStatus());
Advanced Device Operations
getDeviceSpecs() Method
Retrieves detailed specifications and capabilities for a device product.
Signature:
getDeviceSpecs(productId: string): Promise<DeviceSpecifications>
Return Value:
interface DeviceSpecifications {
categoryId: string;
functions: DPFunction[];
status: DPStatus[];
}
interface DPFunction {
code: string; // DP code (e.g., 'switch', 'bright_value')
type: string; // Data type: 'Boolean', 'Value', 'String', 'Enum', 'Raw'
values: string; // JSON string describing value constraints
desc: string; // Human-readable description
}
interface DPStatus {
code: string;
type: string;
values: string;
}
Example:
const specs = await api.getDeviceSpecs('product-light-123');
console.log('Available functions:', specs.functions.map(f => f.code));
// Parse value constraints for a Value-type DP
const brightValueFunc = specs.functions.find(f => f.code === 'bright_value');
if (brightValueFunc) {
const constraints = JSON.parse(brightValueFunc.values);
console.log(`Brightness range: ${constraints.min} - ${constraints.max}`);
console.log(`Scale: ${constraints.scale}`); // e.g., scale=2 means value/100
}
getDeviceLogs() Method
Retrieves historical operation logs for a device.
Signature:
getDeviceLogs(deviceId: string, options?: LogQueryOptions): Promise<DeviceLog[]>
Parameters:
interface LogQueryOptions {
startTime?: number; // Start timestamp (Unix epoch, milliseconds)
endTime?: number; // End timestamp (Unix epoch, milliseconds)
limit?: number; // Maximum records (default: 100, max: 1000)
type?: string; // Log type: 'control', 'status', 'alarm'
}
Return Value:
interface DeviceLog {
id: string;
deviceId: string;
type: string;
operation: string; // e.g., 'dp_send', 'dp_report'
data: Record<string, any>;
timestamp: number;
}
Example:
// Get last 24 hours of control logs
const now = Date.now();
const yesterday = now - (24 * 60 * 60 * 1000);
const logs = await api.getDeviceLogs('ebxxxxxxxxxxxxx', {
startTime: yesterday,
endTime: now,
type: 'control',
limit: 500,
});
console.log(`Found ${logs.length} control operations`);
logs.forEach(log => {
console.log(`${new Date(log.timestamp)}: ${log.operation}`);
});
Scene & Automation API
getScenes() Method
Retrieves all automation scenes configured in your Tuya IoT account.
Signature:
getScenes(options?: SceneQueryOptions): Promise<Scene[]>
Parameters:
interface SceneQueryOptions {
sceneId?: string; // Filter by specific scene ID
name?: string; // Filter by scene name (partial match)
limit?: number; // Maximum results (default: 50)
}
Return Value:
interface Scene {
id: string;
name: string;
description: string;
enabled: boolean;
conditions: SceneCondition[];
actions: SceneAction[];
createTime: number;
updateTime: number;
}
interface SceneCondition {
type: string; // 'device', 'time', 'weather', etc.
expression: string; // Condition logic expression
}
interface SceneAction {
type: string; // 'device_control', 'notification', etc.
deviceId?: string;
commands: Record<string, any>;
}
Example:
const scenes = await api.getScenes();
console.log(`Found ${scenes.length} scenes`);
// Enable a specific scene
const homeScene = scenes.find(s => s.name === 'Home Mode');
if (homeScene) {
await api.enableScene(homeScene.id);
console.log('Home Mode scene enabled');
}
executeScene() Method
Manually triggers a scene execution.
Signature:
executeScene(sceneId: string): Promise<void>
Example:
// Execute "Good Night" scene
await api.executeScene('scene-goodnight-123');
console.log('Good Night scene executed');
createScene() Method
Creates a new automation scene.
Signature:
createScene(sceneConfig: SceneConfig): Promise<Scene>
Example:
const newScene = await api.createScene({
name: 'Morning Routine',
description: 'Turn on lights and coffee maker at 7 AM',
conditions: [
{
type: 'time',
expression: 'CRON(0 7 * * *)', // Every day at 7:00 AM
},
],
actions: [
{
type: 'device_control',
deviceId: 'eb-light-001',
commands: { switch: true, bright_value: 800 },
},
{
type: 'device_control',
deviceId: 'eb-plug-002',
commands: { switch: true },
},
],
});
console.log(`Created scene: ${newScene.id}`);
Webhook Integration
Webhook Subscriptions
Set up webhook subscriptions for real-time device event notifications:
const subscription = await api.subscribeToDeviceEvents({
url: 'https://your-server.com/webhooks/tuya',
events: ['device_status', 'device_online', 'device_offline'],
secret: 'your-webhook-secret', // For HMAC signature verification
});
Webhook payloads include event type, device data, timestamp, and HMAC signature for security verification. Always validate signatures on your endpoint to ensure request authenticity.
Performance Optimization
Request Batching: Execute device operations in parallel using Promise.all() instead of sequential loops:
// ✅ Efficient: Parallel execution
const allStatuses = await Promise.all(devices.map(d => d.getStatus()));
Connection Reuse: Maintain persistent MQTT connections and cache device instances for frequently accessed devices to reduce connection overhead.
Rate Limiting: Implement client-side rate limiting with exponential backoff to avoid API throttling. Track request timestamps and delay when approaching rate limits.
Security Considerations
Credential Management: Never hardcode API credentials. Use environment variables:
const api = new TuyaOpenAPI({
accessId: process.env.TUYA_ACCESS_ID!,
accessSecret: process.env.TUYA_ACCESS_SECRET!,
});
Token Storage: Store session tokens in secure storage (e.g., keytar, encrypted vaults), not plain text.
Input Validation: Always validate DP command inputs before sending to devices to prevent malformed commands.
Best Practices
1. Connection Pooling
For applications managing multiple devices, reuse MQTT connections:
// ❌ Inefficient: New connection per device
for (const deviceId of deviceIds) {
const client = new TuyaMQTTClient(config);
await client.connect();
const device = await client.getDevice(deviceId);
}
// ✅ Efficient: Single connection, multiple devices
const client = new TuyaMQTTClient(config);
await client.connect();
const devices = await Promise.all(
deviceIds.map(id => client.getDevice(id))
);
2. Graceful Shutdown
Always clean up connections on application exit:
class IoTApplication {
private devices: Map<string, TuyaDevice> = new Map();
private mqttClient: TuyaMQTTClient;
async shutdown(): Promise<void> {
console.log('Shutting down...');
// Disconnect all devices
for (const device of this.devices.values()) {
await device.disconnect();
}
// Close MQTT connection
if (this.mqttClient) {
await this.mqttClient.disconnect();
}
console.log('Shutdown complete');
}
}
3. Status Caching
Cache device status to reduce API calls:
class DeviceCache {
private cache: Map<string, { status: any; timestamp: number }> = new Map();
private ttl: number = 5000; // 5 seconds
async getStatus(device: TuyaDevice): Promise<any> {
const cached = this.cache.get(device.id);
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.status;
}
const status = await device.getStatus();
this.cache.set(device.id, { status, timestamp: Date.now() });
return status;
}
}
4. DP Code Discovery
Dynamically discover available DP codes for unknown devices:
async function discoverDPCodes(device: TuyaDevice): Promise<string[]> {
const status = await device.getStatus();
return Object.keys(status);
}
// Usage
const dpCodes = await discoverDPCodes(device);
console.log('Available DP codes:', dpCodes);
Conclusion
This TuyaOpen SDK API reference covers the complete surface area of the tuyaopen framework for IoT development. By understanding each method's parameters, return values, and proper usage patterns, you can build robust, scalable IoT applications that leverage the full power of the Tuya platform.
Key Takeaways:
- Use
TuyaOpenAPIfor authentication and device discovery - Leverage
TuyaMQTTClientfor real-time bidirectional communication - Implement proper token refresh logic for long-running applications
- Handle errors gracefully with retry mechanisms
- Follow connection pooling patterns for multi-device scenarios
For more examples and community discussions, visit the Tuya Developer Community.
Keywords: tuyaopen, SDK API, reference, Tuya IoT, device control, MQTT, TypeScript, JavaScript, IoT development, smart home API
Last updated: April 2026 | Compatible with TuyaOpen SDK v2.x
Top comments (1)
The token refresh pattern with the 5-minute buffer before expiration is one of those details that separates "works in a demo" from "works at 3 AM when nobody's watching." Most SDK references document the
refreshToken()method and move on. Actually showing the scheduling logic—thesetTimeoutthat calls itself recursively, the retry on failure, the buffer to avoid racing the expiration—that's the kind of thing you usually only learn by getting paged.What catches my attention is the
sendCommands()batch method and the connection pooling example at the end. IoT applications tend to start with one device and grow to dozens. The single-device API feels natural at first. Then you're looping over a hundred sensors callinggetStatus()sequentially, wondering why your dashboard takes 45 seconds to load. The parallelPromise.allpattern and the single MQTT connection with multiple devices aren't optimizations—they're architectural decisions that should probably be the default pattern in the examples, not the "best practices" section at the end.The DP code discovery helper is a nice touch for the reality of working with Tuya devices in the wild. The documentation tells you what DP codes a product category should have. The actual device on someone's wall might have a different firmware version with different codes. Being able to introspect at runtime rather than relying on static documentation is the pragmatic move.
The webhook signature verification mention is appropriately brief but it's doing a lot of heavy lifting in one sentence. HMAC verification on webhook endpoints is the kind of thing that's easy to skip in development and catastrophic to skip in production. Is the webhook secret per-account or per-subscription? That distinction matters when you're rotating secrets and don't want to break all your integrations at once.