Connecting to players
Our API lets you connect to your Yoto devices, perform specific actions on them, and receive updates on their state.
This happens via the MQTT protocol. Here’s how it works:
Step 1: Get your devices
Section titled “Step 1: Get your devices”First, fetch your devices from our API:
const deviceResponse = await fetch( "https://api.yotoplay.com/device-v2/devices/mine", { headers: { Authorization: `Bearer ${accessToken}`, }, });const { devices } = await deviceResponse.json();
// select a device to connect toconst deviceId = devices[0].deviceId;Step 2: Connect to the MQTT broker
Section titled “Step 2: Connect to the MQTT broker”The MQTT broker is available at wss://aqrphjqbp3u2z-ats.iot.eu-west-2.amazonaws.com. You’ll need to authenticate using a JWT token with the family:devices:control scope.
const MQTT_URL = "wss://aqrphjqbp3u2z-ats.iot.eu-west-2.amazonaws.com/mqtt";const clientId = `DASH${deviceId}`;
const mqttClient = mqtt.connect(MQTT_URL, { keepalive: 300, port: 443, protocol: "wss", username: `${deviceId}?x-amz-customauthorizer-name=PublicJWTAuthorizer`, password: accessToken, clientId, ALPNProtocols: ["x-amzn-mqtt-ca"],});Step 3: Subscribe to device topics
Section titled “Step 3: Subscribe to device topics”Subscribe to the device topics on connect:
const topics = [ `device/${deviceId}/data/events`, `device/${deviceId}/data/status`, `device/${deviceId}/response`,];
mqttClient.on("connect", function () { mqttClient.subscribe(topics, function (subscribeError) { if (subscribeError) { throw subscribeError; } });});Step 4: Send commands
Section titled “Step 4: Send commands”You can now send commands to your device. For example, to set the volume:
const volumeTopic = `device/${deviceId}/command/volume/set`;const volumePayload = { volume: 3 };mqttClient.publish(volumeTopic, JSON.stringify(volumePayload));Step 5: Handle messages
Section titled “Step 5: Handle messages”The client will receive messages on the subscribed topics:
const eventTopic = `device/${deviceId}/data/events`;const statusTopic = `device/${deviceId}/data/status`;const responseTopic = `device/${deviceId}/response`;
mqttClient.on("message", (topic, message) => { const payload = JSON.parse(message.toString());
if (topic === eventTopic) { // Handle device events } else if (topic === statusTopic) { // Handle status updates } else if (topic === responseTopic) { // Handle command responses }});For a complete status request example, see Getting player status.
Don’t forget to check if the device you’re trying to connect to is online before attempting to connect.
Long-lived integrations
Section titled “Long-lived integrations”If you just need to ask a player something once (read status, send a command, disconnect), you can stop here.
For apps that stay connected to a player, there’s more to handle. Yoto closes idle MQTT connections after about 5 minutes, so a long-running client will drop and need to reconnect. Add two options to your mqtt.connect call, and publish an events request every 4m 55s to keep the connection alive:
const mqttClient = mqtt.connect(MQTT_URL, { keepalive: 300, port: 443, protocol: "wss", username: `${deviceId}?x-amz-customauthorizer-name=PublicJWTAuthorizer`, password: accessToken, reconnectPeriod: 300, clientId, queueQoSZero: true, ALPNProtocols: ["x-amzn-mqtt-ca"],});
const eventsRequestTopic = `device/${deviceId}/command/events/request`;let eventsRequestInterval;
mqttClient.on("connect", function () { mqttClient.subscribe(topics, function (subscribeError) { if (subscribeError) throw subscribeError;
mqttClient.publish(eventsRequestTopic, "{}", { qos: 1 });
clearInterval(eventsRequestInterval); eventsRequestInterval = setInterval(function () { mqttClient.publish(eventsRequestTopic, "{}", { qos: 1 }); }, 295_000); });});
mqttClient.on("reconnect", function () { console.log("Reconnecting to Yoto MQTT broker");});What each highlighted bit does:
reconnectPeriod: 300— if the connection drops, MQTT.js retries every 300ms.queueQoSZero: true— messages you publish while offline are queued and sent once the client reconnects. Without this, commands published during a disconnect are lost.- The
connecthandler fires every time a connection is established — both the first one and any that follow a drop. Subscribing inside it means your subscriptions are restored automatically after a drop, instead of being lost. - The
reconnecthandler fires while MQTT.js is still trying to get a connection back. It’s only useful for logging — resubscribing here would run too early, before the connection exists. - The
setIntervalrepublishes an events request every 4m 55s, keeping the connection from being closed by the broker for inactivity.