Yoto Limiter

API for other apps

With an API key, another app (Home Assistant, a script, a shortcut on your phone) can see how much time a Yoto player has left, pause it, add time, or change its limits, without your password. API keys are part of Plus.

Make a key

In the app, open Settings and find API keys. Give the key a name you will recognise later, tick what it may do, and choose Create key. The key is shown once: copy it into the other app straight away. It starts with yl_.

Keep a key like a password. Anyone who has it can do what it allows on your players until you delete it. Delete a key you no longer use, or one you think someone else has seen; it stops working at once. An account can have 10.

What a key may do

ScopeAllowsYour role on the player
readPlayers' status, the live status stream, play historyMember or owner
controlPause, keep paused (hold), add or take away time todayMember or owner
limitsDaily limits, allowed hours, card rules, starting the day again, the time zoneOwner

A key acts for you: it sees the players you see, and needs both its scope and your role. A key with limits cannot change a player you were only invited to as a member. A key cannot sign in, make other keys, download or delete your account, or change your plan. If your account leaves Plus, its keys stop working until it is back on Plus.

Using a key

Send it in the Authorization header of each request, over HTTPS:

curl -H "Authorization: Bearer yl_…" https://yoto-limiter.com/api/status

That lists every player you can see, with an id for each. The other requests name a player with ?player= and that id. A few examples:

# Pause player 12 now
curl -X POST -H "Authorization: Bearer yl_…" "https://yoto-limiter.com/api/pause?player=12"

# Keep it paused for 30 minutes, then end that early
curl -X POST -H "Authorization: Bearer yl_…" -H "Content-Type: application/json" \
  -d '{"minutes": 30}' "https://yoto-limiter.com/api/hold?player=12"
curl -X DELETE -H "Authorization: Bearer yl_…" "https://yoto-limiter.com/api/hold?player=12"

# Add 15 minutes today (a negative number takes time away)
curl -X POST -H "Authorization: Bearer yl_…" -H "Content-Type: application/json" \
  -d '{"minutes": 15}' "https://yoto-limiter.com/api/extend?player=12"

# Make the daily limit 45 minutes
curl -X PUT -H "Authorization: Bearer yl_…" -H "Content-Type: application/json" \
  -d '{"daily_minutes": 45}' "https://yoto-limiter.com/api/config?player=12"

Every request and answer is described in the OpenAPI description, which tools such as Postman, Insomnia or a client generator can read.

Following changes as they happen

Rather than asking for the status every few seconds, open the live stream and keep it open. Your app makes the connection, so it works from a home network with nothing to open on your router. It sends the status at once and again whenever something changes:

curl -N -H "Authorization: Bearer yl_…" https://yoto-limiter.com/api/events

Each message is an event: status line and a data: line with the same JSON as /api/status. A key may have 2 streams open at once. A stream ends soon after its key is deleted; if yours ends, wait a little before opening it again.

Home Assistant

Put the key in secrets.yaml, with the word Bearer in front:

yoto_limiter_key: "Bearer yl_…"

Then, in configuration.yaml, a sensor with the minutes left and actions to pause and add time (use your player's id):

rest:
  - resource: "https://yoto-limiter.com/api/status"
    headers:
      Authorization: !secret yoto_limiter_key
    scan_interval: 60
    sensor:
      - name: "Yoto minutes left"
        unit_of_measurement: "min"
        value_template: "{{ (value_json.players[0].budget.remaining_secs / 60) | round }}"

rest_command:
  yoto_pause:
    url: "https://yoto-limiter.com/api/pause?player=12"
    method: post
    headers:
      Authorization: !secret yoto_limiter_key
  yoto_add_15:
    url: "https://yoto-limiter.com/api/extend?player=12"
    method: post
    headers:
      Authorization: !secret yoto_limiter_key
    content_type: "application/json"
    payload: '{"minutes": 15}'

The key for this needs read and control.

When something is refused

Errors come back as a status code with a short sentence in plain text, which you can show to people as it is.

401No key, or unknown API key: mistyped, or deleted.
402The account is not on Plus.
403The key does not have the scope (the message names it), or you are a member and only an owner can do that.
404No such player, or not one of yours.
400, 422Something in the request is missing or out of range.
429The key already has 2 live streams open.

A pause goes through Yoto's cloud, so it reaches only a player that is switched on and online (connected in the status). Questions or something missing: [email protected].