Skip to main content

YoLink API

A Python library for interacting with YoLink smart home devices. This library provides async support for authenticating with YoLink's cloud API, managing devices, and receiving real-time MQTT events.

Features

  • OAuth2 Authentication: Secure token-based authentication with automatic refresh
  • Device Management: Enumerate and control all YoLink devices in your home
  • Real-time Events: Subscribe to MQTT events for instant device state updates
  • Multi-region Support: Works with both US and EU YoLink endpoints
  • Async/Await: Fully asynchronous design using aiohttp and aiomqtt

Installation

# Using pip
pip install yolink-api

# Using uv
uv add yolink-api

From Source

git clone https://github.com/YoSmart-Inc/yolink-api.git
cd yolink-api
uv sync

Project Structure

yolink-api/
├── examples/                    # Example scripts for common tasks
│   ├── 01_connect_to_api.py    # Basic API connection
│   ├── 02_enumerate_devices.py # List all devices
│   ├── 03_get_device_state.py  # Query device state
│   ├── 04_control_switch.py    # Control switches/outlets
│   └── 05_mqtt_events.py       # Subscribe to real-time events
├── yolink/                      # Main package
│   ├── auth_mgr.py             # Abstract authentication manager
│   ├── client.py               # HTTP client for API requests
│   ├── client_request.py       # Request model for device commands
│   ├── const.py                # Constants and device type definitions
│   ├── device.py               # YoLinkDevice class and models
│   ├── device_helper.py        # Device utility functions
│   ├── endpoint.py             # API endpoint definitions (US/EU)
│   ├── exception.py            # Custom exception classes
│   ├── home_manager.py         # YoLinkHome manager class
│   ├── message_listener.py     # Abstract MQTT message listener
│   ├── message_resolver.py     # Device-specific message parsing
│   ├── model.py                # BRDP/BSDP data models
│   ├── mqtt_client.py          # MQTT client for real-time events
│   ├── outlet_request_builder.py    # Builder for outlet/switch commands
│   ├── thermostat_request_builder.py # Builder for thermostat commands
│   └── unit_helper.py          # Unit conversion utilities
├── pyproject.toml              # Project metadata and dependencies
└── README.md

Getting Started

1. Obtain API Credentials

To use the YoLink API, you need a User Access ID (UAID) and Secret Key:

  1. Log into your YoLink account at yosmart.com
  2. Navigate to Settings → Account → Advanced Settings → User Access Credentials
  3. Click Generate to create a new UAID/Secret Key pair
  4. Save these credentials securely - you'll need them for API access

2. Set Environment Variables

Export your credentials as environment variables:

export YOLINK_UAID="your_user_access_id"
export YOLINK_SECRET_KEY="your_secret_key"

3. Run an Example

# Connect to the API and verify credentials
python examples/01_connect_to_api.py

# List all your devices
python examples/02_enumerate_devices.py

Quickstart

Connect to the API

import asyncio
from datetime import datetime, timedelta, timezone

import aiohttp

from yolink.auth_mgr import YoLinkAuthMgr
from yolink.client import YoLinkClient
from yolink.const import OAUTH2_TOKEN
from yolink.endpoint import Endpoints


class SimpleAuthManager(YoLinkAuthMgr):
    """Simple auth manager implementation."""
    
    def __init__(self, session: aiohttp.ClientSession, uaid: str, secret_key: str):
        super().__init__(session)
        self._uaid = uaid
        self._secret_key = secret_key
        self._access_token = None
        self._token_expires_at = None
    
    def access_token(self) -> str:
        return self._access_token or ""
    
    async def check_and_refresh_token(self) -> str:
        if (
            self._access_token is None
            or self._token_expires_at is None
            or datetime.now(timezone.utc) >= self._token_expires_at - timedelta(minutes=5)
        ):
            await self._fetch_token()
        return self._access_token
    
    async def _fetch_token(self) -> None:
        async with self._session.post(
            OAUTH2_TOKEN,
            data={
                "grant_type": "client_credentials",
                "client_id": self._uaid,
                "client_secret": self._secret_key,
            },
        ) as response:
            response.raise_for_status()
            data = await response.json()
            self._access_token = data["access_token"]
            expires_in = data.get("expires_in", 7200)
            self._token_expires_at = datetime.now(timezone.utc) + timedelta(seconds=expires_in)


async def main():
    uaid = "your_uaid"
    secret_key = "your_secret_key"
    
    async with aiohttp.ClientSession() as session:
        auth_mgr = SimpleAuthManager(session, uaid, secret_key)
        client = YoLinkClient(auth_mgr)
        
        # Authenticate
        await auth_mgr.check_and_refresh_token()
        print("Connected!")

asyncio.run(main())

Enumerate Devices

async def list_devices(client: YoLinkClient):
    response = await client.execute(
        url=Endpoints.US.value.url,
        bsdp={"method": "Home.getDeviceList"}
    )
    
    for device in response.data.get("devices", []):
        print(f"{device['name']} ({device['type']}) - {device['deviceId']}")

Get Device State

from yolink.device import YoLinkDevice, YoLinkDeviceMode

async def get_device_state(client: YoLinkClient, device_data: dict):
    # Create a device instance from the device data
    device_mode = YoLinkDeviceMode(**device_data)
    device = YoLinkDevice(device_mode, client)
    
    # Get current state
    state = await device.get_state()
    print(f"State: {state.data}")

Control a Switch

from yolink.outlet_request_builder import OutletRequestBuilder

async def toggle_switch(device: YoLinkDevice, turn_on: bool):
    # "open" = ON, "close" = OFF
    state = "open" if turn_on else "close"
    request = OutletRequestBuilder.set_state_request(state=state, plug_indx=None)
    result = await device.call_device(request)
    
    if result.code == "000000":
        print("Success!")
    else:
        print(f"Failed: {result.desc}")

Subscribe to MQTT Events

import aiomqtt

async def listen_for_events(auth_mgr: SimpleAuthManager, home_id: str):
    topic = f"yl-home/{home_id}/+/report"
    
    async with aiomqtt.Client(
        hostname=Endpoints.US.value.mqtt_broker_host,
        port=Endpoints.US.value.mqtt_broker_port,
        username=auth_mgr.access_token(),
        password="",
        keepalive=60,
    ) as client:
        await client.subscribe(topic)
        
        async for message in client.messages:
            print(f"Event: {message.payload.decode()}")

Supported Devices

This library supports a wide range of YoLink devices including:

Category Device Types
Hubs Hub (YS1603-UC), SpeakerHub (YS1604-UC)
Sensors Door Sensor, Motion Sensor, Water Leak Sensor, Temperature/Humidity Sensor, Vibration Sensor, CO/Smoke Alarm, Soil Sensor
Switches & Outlets In-Wall Switch, Outlet, Multi-Outlet, Smart Plug, Power Strip
Controllers Thermostat, Garage Door Controller, Water Valve, Sprinkler Controller
Locks Smart Lock M1, Smart Lock M2
Remotes KeyFob, On/Off Fob, DimmerFob, SirenFob, FlexFob
Alarms Siren Alarm, Outdoor Alarm, Power Fail Alarm

See the full device list below for specific model numbers.

API Reference

YoLinkAuthMgr (Abstract Base Class)

The authentication manager handles OAuth2 token management. You must implement:

  • access_token() -> str: Return the current access token
  • check_and_refresh_token() -> str: Ensure token is valid, refresh if needed

YoLinkClient

The HTTP client for making API requests:

  • execute(url, bsdp, **kwargs) -> BRDP: Execute an API request
  • get(url, **kwargs) -> ClientResponse: Make a GET request
  • post(url, **kwargs) -> ClientResponse: Make a POST request

YoLinkDevice

Represents a single YoLink device:

  • get_state() -> BRDP: Get real-time device state
  • fetch_state() -> BRDP: Fetch cached device state
  • call_device(request: ClientRequest) -> BRDP: Send a command to the device

YoLinkHome

High-level manager for your YoLink home (used for Home Assistant integration):

  • async_setup(auth_mgr, listener): Initialize the home manager
  • async_unload(): Clean up resources
  • get_devices() -> list[YoLinkDevice]: Get all devices
  • get_device(device_id) -> YoLinkDevice: Get a specific device

Device Models

Click to expand full device list
  • YS1603-UC (Hub)
  • YS1604-UC (SpeakerHub)
  • YS3604-UC (YoLink KeyFob)
  • YS3605-UC (YoLink On/OffFob)
  • YS3606-UC (YoLink DimmerFob)
  • YS3607-UC (YoLink SirenFob)
  • YS3614-UC (YoLink Mini FlexFob)
  • YS4002-UC (YoLink Thermostat)
  • YS4003-UC (YoLink Thermostat Heatpump)
  • YS4906-UC + YS7706-UC (Garage Door Kit 1)
  • YS4908-UC + YS7706-UC (Garage Door Kit 2 (Finger))
  • YS4909-UC (Water Valve Controller)
  • YS5001-UC (X3 Water Valve Controller)
  • YS5002-UC (YoLink Motorized Ball Valve)
  • YS5003-UC (Water Valve Controller 2)
  • YS5705-UC (In-Wall Switch)
  • YS5706-UC (YoLink Relay)
  • YS5707-UC (Dimmer Switch)
  • YS5708-UC (In-Wall Switch 2)
  • YS6602-UC (YoLink Energy Plug)
  • YS6604-UC (YoLink Plug Mini)
  • YS6704-UC (In-wall Outlet)
  • YS6801-UC (Smart Power Strip)
  • YS6802-UC (Smart Outdoor Power Strip)
  • YS6803-UC (Outdoor Energy Plug)
  • YS7103-UC (Siren Alarm)
  • YS7104-UC (Outdoor Alarm Controller)
  • YS7105-UC (X3 Outdoor Alarm Controller)
  • YS7106-UC (Power Fail Alarm)
  • YS7107-UC (Outdoor Alarm Controller 2)
  • YS7201-UC (Vibration Sensor)
  • YS7606-UC (YoLink Smart Lock M1)
  • YS7607-UC (YoLink Smart Lock M2)
  • YS7704-UC (Door Sensor)
  • YS7706-UC (Garage Door Sensor)
  • YS7707-UC (Contact Sensor)
  • YS7804-UC (Motion Sensor)
  • YS7805-UC (Outdoor Motion Sensor)
  • YS7903-UC (Water Leak Sensor)
  • YS7904-UC (Water Leak Sensor 2)
  • YS7906-UC (Water Leak Sensor 4)
  • YS7916-UC (Water Leak Sensor 4 MoveAlert)
  • YS7905-UC (WaterDepthSensor)
  • YS7A01-UC (Smart Smoke/CO Alarm)
  • YS8003-UC (Temperature Humidity Sensor)
  • YS8004-UC (Weatherproof Temperature Sensor)
  • YS8005-UC (Weatherproof Temperature & Humidity Sensor)
  • YS8006-UC (X3 Temperature & Humidity Sensor)
  • YS8014-UC (X3 Outdoor Temperature Sensor)
  • YS8015-UC (X3 Outdoor Temperature & Humidity Sensor)
  • YS5006-UC (FlowSmart Control)
  • YS5007-UC (FlowSmart Meter)
  • YS5008-UC (FlowSmart All-in-One)
  • YS8017-UC (Thermometer)
  • YS5009-UC (LeakStop Controller)
  • YS5029-UC (LeakStop Controller 2 Channel)
  • YS8009-UC (Soil Temperature & Humidity Sensor)
  • YS4102-UC (Smart Sprinkler Controller)
  • YS4103-UC (Smart Sprinkler Controller V2)
  • YS7A12-UC (Smoke Alarm)
  • YS7A06-UC (Smart CO Alarm)

Error Handling

The library defines several exception types:

  • YoLinkError: Base exception class
  • YoLinkClientError: API request errors
  • YoLinkAuthFailError: Authentication failures
  • YoLinkDeviceConnectionFailed: Device communication errors
  • YoLinkUnSupportedMethodError: Unsupported device operations
from yolink.exception import YoLinkClientError, YoLinkAuthFailError

try:
    await device.get_state()
except YoLinkAuthFailError:
    print("Authentication failed - check your credentials")
except YoLinkClientError as e:
    print(f"API error {e.code}: {e.message}")

Dependencies

  • aiohttp>=3.8.1 - Async HTTP client
  • aiomqtt>=2.0.0,<3.0.0 - Async MQTT client
  • pydantic>=2.0.0 - Data validation
  • tenacity>=8.1.0 - Retry logic

License

MIT License - see LICENSE for details.

Metadata

Release files for yolink-api 0.6.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yolink-api 0.6.5
File Size Uploaded
yolink_api-0.6.5.tar.gz 22.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for yolink-api 0.6.5
File Interpreter ABI Platform
yolink_api-0.6.5-py3-none-any.whl Python 3 none any Details

Total release size: 47.1 kB

Release history Release notifications | RSS feed

This release

0.6.5 This release

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.9

2 release files

0.5.8

2 release files

0.5.7

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.5

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page