Skip to content

Technical

The Yapaia protocol (v1)

How modules register with the integration, describe themselves, deliver their values and receive commands – the interface for building along.

Overview

The protocol connects every Yapaia module to the central Home Assistant integration “Yapaia”. All paths use HTTP and WebSocket on Home Assistant’s internal network. Field names are German by design – they are part of the contract.

 Module (add-on)                                     “yapaia” integration
   │ 1. Register: Supervisor discovery “yapaia”   ─────▶ │
   │ 2. GET  /yapaia/v1/beschreibung              ◀───── │
   │ 3. WS   /yapaia/v1/live   (states, events)   ══▶    │
   │ 4. POST /yapaia/v1/aktion/<name>             ◀───── │
   │ 5. POST /yapaia/v1/partner (who else is here)◀───── │

Every call carries Authorization: Bearer <token>. Without a valid token the interface answers 401.

Modules and instances

A module can have several instances (e.g. several satellites). Every instance carries:

FieldMeaning
modulkind of building block: go, beat, satellite …
instanzpermanent, unique id generated by the module; never changes
namedisplay name, changeable by the user
  • Every instance is its own device and config entry in Home Assistant.
  • Unique id of an entity: yapaia_<modul>_<instanz>_<schluessel>.
  • Entity id: <platform>.yapaia_<modul>_<schluessel>, e.g. sensor.yapaia_go_ankunft.
  • Actions are called yapaia.<modul>_<name>, e.g. yapaia.go_ziel_setzen.

1. Registration

On start, the add-on registers with the Supervisor (POST /discovery):

{
  "service": "yapaia",
  "config": {
    "modul": "go",
    "instanz": "7f3c9a2e",
    "name": "Yapaia Go",
    "host": "a0d7b954-yapaia-go",
    "port": 8080,
    "token": "…32 Byte, base64url…",
    "protokoll": 1,
    "version": "0.46.0"
  }
}

Home Assistant then shows “Yapaia Go discovered”. The add-on creates the token once and stores it in its private /data.

2. Description

GET /yapaia/v1/beschreibung tells what the module offers:

{
  "protokoll": 1,
  "modul": "go",
  "instanz": "7f3c9a2e",
  "name": "Yapaia Go",
  "version": "0.46.0",
  "hersteller": "Yapaia",
  "faehigkeiten": ["navigation"],
  "entitaeten": [
    { "schluessel": "restweg", "plattform": "sensor",
      "name": { "de": "Restweg", "en": "Distance remaining" },
      "geraeteklasse": "distance", "einheit": "km", "zustandsklasse": "measurement" },
    { "schluessel": "profil", "plattform": "select",
      "name": { "de": "Fahrzeugprofil", "en": "Vehicle profile" },
      "optionen_aus": "profile", "aktion": "profil_waehlen" }
  ],
  "aktionen": [
    { "name": "ziel_setzen", "titel": { "de": "Ziel setzen", "en": "Set destination" },
      "felder": { "ziel": { "typ": "text", "titel": { "de": "Adresse oder Ort" } } } }
  ],
  "ereignisse": [
    { "name": "ziel_erreicht", "titel": { "de": "Ziel erreicht" }, "daten": ["ziel"] }
  ]
}

Entity fields

FieldMeaning
schluesselpermanent key within the module – never rename
plattformsensor, binary_sensor, switch, select, number, button, text, device_tracker, camera, image, event or spezial
namedisplay name per language
geraeteklasse, einheit, zustandsklasse, symboldevice class, unit, state class, icon – as in Home Assistant
symbol_ausstate key whose value replaces the icon
kategorieconfig or diagnostic
standard_aktivfalse = disabled by default
aktion, aktion_an, aktion_auswhich action operating the entity triggers
optionen / optionen_ausfixed list, or the state key that provides it
min, max, schrittfor number
attributestate keys passed along as attributes

A device_tracker has the value {"breite": 52.1, "laenge": 11.6, "genauigkeit": 5} (latitude, longitude, accuracy in m) or null.

A camera names two paths on the module: bild (a JPEG) and stream (MJPEG). The integration fetches both with the token and passes them on to Home Assistant.

Actions and events

  • Field types for actions: text, zahl (number), bool, auswahl (choice, with optionen), entitaet (entity), ort (location).
  • The integration fires events as the Home Assistant event yapaia_ereignis (with modul, instanz, geraet_id, name, daten) and offers them as device triggers.

3. Live connection

GET /yapaia/v1/live (WebSocket). The module sends:

{"typ": "zustand", "werte": {"ankunft": "2026-10-11T18:42:00+02:00", "restweg": 132.4}}
{"typ": "ereignis", "name": "ziel_erreicht", "daten": {"ziel": "Magdeburg"}}
{"typ": "beschreibung_geaendert"}
  • Right after connecting: one complete zustand (state), afterwards only changes.
  • null means unknown.
  • If the connection drops, the entities become unavailable; the integration reconnects (1, 2, 4 … at most 60 s).
  • Fast-changing values (speed, position) at most once per second.

4. Running actions

POST /yapaia/v1/aktion/<name> with the fields as JSON.

  • Success: 200 {"ok": true}, optionally with "ergebnis" (result).
  • Error: 4xx/5xx {"ok": false, "fehler": "message for the user"} – shown in Home Assistant as the action’s error.
  • The module reports the new state over the live connection, not in the response. That way there is only one source of state.

5. Partners

The integration tells every module who else is around:

POST /yapaia/v1/partner

{"partner": [
  {"modul": "beat", "instanz": "c41b07d2", "name": "Yapaia Beat",
   "url": "http://a0d7b954-yapaia-beat:8099", "token": "…",
   "version": "1.14.1", "faehigkeiten": ["radio", "ansage.einmischen"]},
  {"modul": "satellite", "instanz": "a4cf12b3e8d0", "name": "Yapaia Satellite Küche",
   "media_player": "media_player.yapaia_satellite_kuche",
   "faehigkeiten": ["sprache.eingabe", "sprache.ausgabe"]}
]}

Sent after setup and on every change. An empty list means: alone. Modules use partners only through announced capabilities.

Versions

  • protokoll is an integer. New fields, entities, actions, events and capabilities do not change it – both sides ignore what they do not know.
  • Only what breaks existing behaviour increases it. The integration then supports old and new version for at least one add-on generation.

Building your own module

A new module needs no integration code: it registers via discovery, provides a description, keeps a live connection and accepts actions. Without a Supervisor (development, Docker) you enter host, port and token in the integration by hand.