Zum Inhalt springen
Developer

HomeAssistant

Smart Home und Automationen20 EndpunkteDataWarehouse / HomeAssistant

Liefert eine Liste buchbarer Ressourcen für Home Assistant.

GET/api/homeassistant/bookables

Jeder Eintrag enthält id und name.

Antworten

default

Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/bookables \
  --header 'x-iw-jwt-token: <TOKEN>'

Liefert einen Kalender-Feed (iCal) für eine einzelne buchbare Ressource.

GET/api/homeassistant/calendar/{identifier}

Pfad-Parameter

identifierPflichtstring

Antworten

default

Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/calendar/42 \
  --header 'x-iw-jwt-token: <TOKEN>'

Liefert den iCal für einen einzelnen Buchungseintrag sowie dessen Buchbar-ID.

GET/api/homeassistant/booking/{identifier}

Wird vom Webhook-Handler genutzt, um eine einzelne Veranstaltung in den Kalender zu übernehmen, ohne den vollständigen Kalender-Feed abzurufen.

Pfad-Parameter

identifierPflichtstring

Antworten

default

Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/booking/42 \
  --header 'x-iw-jwt-token: <TOKEN>'

Einen Webhook registrieren, damit das ERP Home Assistant benachrichtigt, wenn sich Buchungen ändern.

POST/api/homeassistant/webhook

Erwartet JSON-Body: {"webhook_url": "https://ha-instance/api/webhook/iw_erp_homeassistant"}

Legt einen RegisteredWebhook-Eintrag für BaseBooking-Ereignisse (Anlegen, Ändern, Löschen) an.

Optional "events": ["access", "check_in"] - mit integration_ha_access_events_enabled meldet die ERP außerdem Smart-Lock-Zugriffe und Check-ins an dieselbe URL (Body ohne die Entität, nur webhook_data). Jede Registrierung gibt die vollständige Liste an: weggelassene Ereignisse werden entfernt. Die Antwort enthält dann "events" mit den aktiven Ereignissen.

Optional "webhook_token": ein Geheimnis aus 16-190 druckbaren Zeichen, das mit jedem Webhook der URL als X-IW-Webhook-Token zurückgesendet wird, damit Home Assistant gefälschte Aufrufe ablehnen kann.

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/webhook \
  --header 'x-iw-jwt-token: <TOKEN>'

Home-Assistant-Webhook abmelden.

DELETE/api/homeassistant/webhook

Erwartet JSON-Body: {"webhook_url": "https://ha-instance/api/webhook/iw_erp_homeassistant"}

Antworten

default

Anfrage
curl --request DELETE \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/webhook \
  --header 'x-iw-jwt-token: <TOKEN>'

ERP-Smart-Locks, die der Benutzer des API-Schlüssels verwenden darf, für die Lock-Entitäten der Home-Assistant-Integration ("ERP-Smart-Locks importieren", Opt-in in Home Assistant). Schlösser, die die aufrufende Home-Assistant-Instanz selbst anbietet, bleiben außen vor (excludeHaInstanceId).

GET/api/homeassistant/smart_locks

Query-Parameter

excludeHaInstanceIdstringHome-Assistant-Instanz-ID, deren eigene Schlösser übersprungen werden

Antworten

200Smart Locks, die für den Benutzer des API-Schlüssels zugänglich sindarray<object>

Felder anzeigen (4)
  • idinteger
  • namestring
  • descriptionstring
  • typestring
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/smart_locks \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
[
  {
    "id": 42,
    "name": "Beispiel",
    "description": "Text",
    "type": "string"
  }
]
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/smart_locks/42/status \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
{
  "id": 42,
  "state": "string"
}

Sperrt ein ERP-Smart-Lock aus Home Assistant. Gleiche Zugriffsregeln und gleiches Smart-Lock-Protokoll wie /api/event/smart_lock/{id}/lock.

POST/api/homeassistant/smart_locks/{identifier}/lock

Pfad-Parameter

identifierPflichtstring

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/smart_locks/42/lock \
  --header 'x-iw-jwt-token: <TOKEN>'

Öffnet ein ERP-Smart-Lock aus Home Assistant. Gleiche Zugriffsregeln und Smart-Lock-Protokollierung wie /api/event/smart_lock/{id}/unlock.

POST/api/homeassistant/smart_locks/{identifier}/unlock

Pfad-Parameter

identifierPflichtstring

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/smart_locks/42/unlock \
  --header 'x-iw-jwt-token: <TOKEN>'

Home Assistant bietet seine Schlösser der ERP an ("Home-Assistant-Schlösser anbieten", Opt-in in Home Assistant).

POST/api/homeassistant/ha_locks

Erstellt oder aktualisiert eine Smart-Lock-Verbindung (Anbieter "homeassistant") für die Instanz. Die Schlösser werden erst dann zu ERP-Smart-Locks, wenn ein Administrator die Geräte dieser Verbindung synchronisiert.

Erwartet JSON-Body: { "instance_id": "", "name": "Home Assistant", "webhook_url": "https://ha.example.com/api/webhook/iw_erp_homeassistant", "secret": "<gemeinsames HMAC-Secret für Schloss-Befehle>", "locks": [{"entity_id": "lock.front_door", "name": "Front door", "state": "locked", "supports_open": true}] }

Eine bereits verbundene Instanz muss das Secret senden, mit dem sie sich registriert hat. Nachdem die Verbindung entfernt wurde (DELETE), kann sich die Instanz mit einem neuen Secret erneut registrieren.

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/ha_locks \
  --header 'x-iw-jwt-token: <TOKEN>'

Home Assistant bietet seine Schlösser nicht mehr an (Opt-in ausgeschaltet oder Integration entfernt).

DELETE/api/homeassistant/ha_locks

Erwartet JSON-Body: {"instance_id": "...", "secret": "..."}. Markiert die Verbindung als gelöscht; ihre Smart-Locks bleiben bestehen, können aber erst wieder verwendet werden, wenn sich die Instanz erneut registriert.

Antworten

default

Anfrage
curl --request DELETE \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/ha_locks \
  --header 'x-iw-jwt-token: <TOKEN>'

Raumanzeigen, an die Home Assistant ausliefert: die OpenDisplay-Empfänger.

GET/api/homeassistant/displays

OpenDisplay-Anzeigen werden von einem Sender in ihrer Nähe per Bluetooth angesteuert, und Home Assistant mit der OpenDisplay-Integration ist genau das. Home Assistant authentifiziert sich hier mit seinem API-Token, sodass kein Gerätegeheimnis in seine Konfiguration kopiert werden muss.

Antworten

200OpenDisplay-Empfängerarray<object>

Felder anzeigen (7)
  • idinteger
  • namestring
  • device_idstring
  • targetstring
  • refresh_secondsinteger
  • widthinteger
  • heightinteger
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/displays \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
[
  {
    "id": 42,
    "name": "Beispiel",
    "device_id": "42",
    "target": "string",
    "refresh_seconds": 1,
    "width": 1,
    "height": 1
  }
]

Das aktuelle Bild eines OpenDisplay-Empfängers, das Home Assistant hochlädt.

GET/api/homeassistant/displays/{identifier}/frame.png

Dieselbe Antwort wie der Gerätepfad /display/opendisplay/{deviceId} – PNG, ETag / If-None-Match, X-Refresh-After – authentifiziert mit dem API-Token statt mit dem Gerätegeheimnis. Das Abrufen ist keine Telemetrie: Dass Home Assistant läuft, sagt nichts über das Panel aus, daher wird lastSeenAt nicht verändert.

Pfad-Parameter

identifierPflichtstring

Antworten

200Rahmen als PNG in der Auflösung des Panels

304Rahmen unverändert, nicht hochladen

Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/displays/42/frame.png \
  --header 'x-iw-jwt-token: <TOKEN>'

Was Home Assistant über das Panel weiß: Batterie, Signal, Firmware und wann zuletzt ein Lebenszeichen empfangen wurde.

POST/api/homeassistant/displays/{identifier}/telemetry

last_seen ist der letzte Kontakt des Panels, so wie Home Assistant ihn sah, nicht der Zeitpunkt dieser Anfrage – der Offline-Bericht muss ein totes Panel hinter einem lebenden Home Assistant erkennen. Ohne diesen Wert zählt der gerade erfolgreiche Upload.

Pfad-Parameter

identifierPflichtstring

Request-Body application/json

  • battery_mvnumber
  • battery_voltagenumber
  • rssiinteger
  • firmwarestring
  • last_seenstring (date-time)

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/displays/42/telemetry \
  --header 'content-type: application/json' \
  --header 'x-iw-jwt-token: <TOKEN>' \
  --data '
{
  "battery_mv": 1.5,
  "battery_voltage": 1.5,
  "rssi": 1,
  "firmware": "string",
  "last_seen": "2026-10-15T09:30:00+02:00"
}
'

Belegung der buchbaren Ressourcen für die Belegungssensoren (integration_occupancy_api_enabled): aktuelle Buchung, Vorlaufzeit bis zur nächsten, Nachlaufzeit nach der letzten, nächste Buchung, Öffnungszeiten.

GET/api/homeassistant/occupancy

Auch bereitgestellt unter /api/event/bookable_occupancy für Node-RED und n8n.

Query-Parameter

bookablestringKommagetrennte IDs buchbarer Objekte, Standard: alle

Antworten

200Belegung je buchbarer Ressourceobject

Felder anzeigen (2)
  • generated_atstring (date-time)
  • bookablesarray<object>
    Felder anzeigen (12)
    • idinteger
    • namestring
    • location_idinteger
    • location_namestring
    • occupiedboolean
    • pre_start_activeboolean
    • post_end_activeboolean
    • pre_start_minutesinteger
    • post_end_minutesinteger
    • current_bookingobject
    • next_bookingobject
    • opening_hoursobject
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/occupancy \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
{
  "generated_at": "2026-10-15T09:30:00+02:00",
  "bookables": [
    {
      "id": 42,
      "name": "Beispiel",
      "location_name": "Beispiel",
      "location_id": 42,
      "occupied": true,
      "pre_start_active": true,
      "post_end_active": true,
      "pre_start_minutes": 1,
      "post_end_minutes": 1
    }
  ]
}

Nutzungszähler der Buchbaren, für Zähler, die Home Assistant meldet (integration_usage_counter_api_enabled).

GET/api/homeassistant/usage_counters

Antworten

200Nutzungszählerarray<object>

Felder anzeigen (8)
  • idinteger
  • namestring
  • bookable_idinteger
  • bookable_namestring
  • valuenumber
  • unitstring
  • use_real_usage_databoolean
  • updatedstring (date-time)
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/usage_counters \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
[
  {
    "id": 42,
    "name": "Beispiel",
    "bookable_name": "Beispiel",
    "bookable_id": 42,
    "value": 1.5,
    "unit": "string",
    "use_real_usage_data": true,
    "updated": "2026-10-15T09:30:00+02:00"
  }
]

Ein Zählerstand von Home Assistant: setzt den Wert eines Verbrauchszählers. Zähler, die mit den echten Nutzungsdaten der Buchungen gefüllt werden, werden abgelehnt, da Home Assistant deren Summen überschreiben würde.

POST/api/homeassistant/usage_counters/{identifier}

Erwartet JSON-Body {"value": 1240.2}.

Pfad-Parameter

identifierPflichtstring

Request-Body application/json

  • valuenumber

Antworten

default

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/usage_counters/42 \
  --header 'content-type: application/json' \
  --header 'x-iw-jwt-token: <TOKEN>' \
  --data '{"value":1.5}'

Darf ein Berechtigungsnachweis, den ein Leser bei Home Assistant liest (RFID-Karte, QR der Mitgliedskarte, Zugangscode der App), ein Schloss öffnen (integration_ha_access_check_enabled)? Gleiche Regeln und gleiches Smart-Lock-Protokoll wie die Zugangsprüfung von Node-RED, mit der Quelle "homeassistant".

POST/api/homeassistant/check_access

Erwartet JSON-Body: { "credential": "04A1B2C3D4", "credential_type": "auto", // auto, access_code, member_card oder card "smart_lock_id": 12, // beliebiges ERP-Smart-Lock "instance_id": "...", "lock_id": "lock.front_door", // oder ein Schloss, das diese Home Assistant anbietet "open": false // die ERP öffnet ein Schloss eines anderen Anbieters selbst }

Antworten

200Zugriffsentscheidungobject

Felder anzeigen (6)
  • grantedboolean
  • reasonstring
  • credential_typestring
  • smart_lockobject
  • personobject
  • openedboolean
Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/check_access \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
{
  "granted": true,
  "reason": "string",
  "credential_type": "string",
  "opened": true
}

Eine Störungsmeldung von Home Assistant als Ticket (integration_ha_ticket_enabled), z. B. ein Wasseralarm.

POST/api/homeassistant/ticket

Erwartet JSON-Body {"title": "...", "description": "...", "bookable_id": 7, "priority": "low|normal|high|urgent", "dedupe_key": "water_leak_hall_1"}; solange ein Ticket mit dem Dedupe-Schlüssel offen ist, wird kein zweites angelegt.

Antworten

200Ticketobject

Felder anzeigen (2)
  • idinteger
  • statusstring

    created oder already_open

Anfrage
curl --request POST \
  --url https://eure-instanz.iw-erp.de/api/homeassistant/ticket \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
{
  "id": 42,
  "status": "string"
}

Belegung der buchbaren Ressourcen für die Belegungssensoren (integration_occupancy_api_enabled): aktuelle Buchung, Vorlaufzeit bis zur nächsten, Nachlaufzeit nach der letzten, nächste Buchung, Öffnungszeiten.

GET/api/event/bookable_occupancy

Auch bereitgestellt unter /api/event/bookable_occupancy für Node-RED und n8n.

Query-Parameter

bookablestringKommagetrennte IDs buchbarer Objekte, Standard: alle

Antworten

200Belegung je buchbarer Ressourceobject

Felder anzeigen (2)
  • generated_atstring (date-time)
  • bookablesarray<object>
    Felder anzeigen (12)
    • idinteger
    • namestring
    • location_idinteger
    • location_namestring
    • occupiedboolean
    • pre_start_activeboolean
    • post_end_activeboolean
    • pre_start_minutesinteger
    • post_end_minutesinteger
    • current_bookingobject
    • next_bookingobject
    • opening_hoursobject
Anfrage
curl --request GET \
  --url https://eure-instanz.iw-erp.de/api/event/bookable_occupancy \
  --header 'x-iw-jwt-token: <TOKEN>'
Antwort 200 application/json
{
  "generated_at": "2026-10-15T09:30:00+02:00",
  "bookables": [
    {
      "id": 42,
      "name": "Beispiel",
      "location_name": "Beispiel",
      "location_id": 42,
      "occupied": true,
      "pre_start_active": true,
      "post_end_active": true,
      "pre_start_minutes": 1,
      "post_end_minutes": 1
    }
  ]
}