{"scopes":[{"id":"billy:read","label":"Billy-Einblicke lesen","unit":"core"},{"id":"billy:write","label":"Billy-Vorschläge/Feedback schreiben","unit":"core"},{"id":"iot:read","label":"IoT-Messpunkte & Werte lesen","unit":"iot"},{"id":"iot:write","label":"IoT-Werte einspielen (Ingest)","unit":"iot"},{"id":"hotel:read","label":"Hotel-Übersicht & Zimmer lesen","unit":"hotel"},{"id":"hotel:write","label":"Hotel-Buchungen/Umsätze schreiben","unit":"hotel"},{"id":"arbitrage:read","label":"Arbitrage-Übersicht & Vorschläge lesen","unit":"arbitrage"},{"id":"arbitrage:write","label":"Arbitrage-Vorschläge bestätigen","unit":"arbitrage"},{"id":"accounting:read","label":"Rechnungs-/Buchhaltungs-Übersicht lesen","unit":"accounting"}],"units":[{"id":"core","label":"Billy Core","description":"Zentrale Einblicke/Insights der Billy-Engine.","scopes":["billy:read","billy:write"],"endpoints":[{"method":"GET","path":"/api/ext/v1/billy/insights","scope":"billy:read","desc":"Aktuelle Vorschläge/Warnungen (Insights)."}]},{"id":"iot","label":"IoT-Einheit","description":"Messpunkte (Sensoren/Zähler), Werte-Ingest und Status.","scopes":["iot:read","iot:write"],"endpoints":[{"method":"GET","path":"/api/ext/v1/iot/overview","scope":"iot:read","desc":"Alle Messpunkte mit letztem Wert + Status."},{"method":"GET","path":"/api/ext/v1/iot/devices/:id","scope":"iot:read","desc":"Ein Messpunkt inkl. Verlauf."},{"method":"POST","path":"/api/ext/v1/iot/ingest","scope":"iot:write","desc":"Wert einspielen: { device_id, value, ts? }. Unbekannte Geräte werden angelegt."},{"method":"POST","path":"/api/ext/v1/iot/devices/:id/event","scope":"iot:write","desc":"Status-/Tür-/Smart-Lock-/Gateway-Event schreiben: { status, event, ts? }."},{"method":"POST","path":"/api/ext/v1/iot/devices/:id/post-to-folio","scope":"iot:write","desc":"Abrechenbares IoT-Event auf ein Hotel-Folio buchen."},{"method":"GET","path":"/api/ext/v1/iot/energy","scope":"iot:read","desc":"Energie-Aggregation (Tages-/Monats-kWh + Kosten); ?device=&period=day|month&price=."},{"method":"POST","path":"/api/ext/v1/ocpp/:chargerId/frame","scope":"iot:write","desc":"OCPP 1.6J Frame einer Ladestation einspielen."},{"method":"GET","path":"/api/ext/v1/ocpp/:chargerId/commands","scope":"iot:write","desc":"Anstehende Server→Lader-Kommandos abholen (OCPP-CALL-Frames, z. B. SetChargingProfile)."},{"method":"POST","path":"/api/ext/v1/ocpp/sessions/:id/post-to-folio","scope":"iot:write","desc":"EV-Ladesession nach StopTransaction auf ein Hotel-Folio buchen."},{"method":"POST","path":"/api/ext/v1/iot/prices","scope":"iot:write","desc":"Strombörsen-Preisslots einspielen (Day-Ahead; slots:[{start,end,ct}] in ct/kWh)."}]},{"id":"hotel","label":"Hotel-Einheit","description":"Zimmer, Folio/Tagesblatt, Check-in/out.","scopes":["hotel:read","hotel:write"],"endpoints":[{"method":"GET","path":"/api/ext/v1/hotel/overview","scope":"hotel:read","desc":"Zimmerstatus, Auslastung, Tagesumsatz."},{"method":"GET","path":"/api/ext/v1/hotel/rooms/:id/day","scope":"hotel:read","desc":"Tagesblatt eines Zimmers."},{"method":"POST","path":"/api/ext/v1/hotel/rooms/:id/charges","scope":"hotel:write","desc":"Umsatz buchen: { category, description, qty, unit_price }."}]},{"id":"arbitrage","label":"Arbitrage-Einheit","description":"Lieferanten-Arbitrage, Billy-Vorschläge, Veröffentlichung.","scopes":["arbitrage:read","arbitrage:write"],"endpoints":[{"method":"GET","path":"/api/ext/v1/arbitrage/overview","scope":"arbitrage:read","desc":"Kennzahlen des Arbitrage-Hubs."},{"method":"GET","path":"/api/ext/v1/arbitrage/proposals","scope":"arbitrage:read","desc":"Offene Billy-Vorschläge."},{"method":"POST","path":"/api/ext/v1/arbitrage/proposals/generate","scope":"arbitrage:write","desc":"Neue Billy-Vorschläge generieren."},{"method":"POST","path":"/api/ext/v1/arbitrage/proposals/:id/confirm","scope":"arbitrage:write","desc":"Billy-Vorschlag bestätigen und veröffentlichen."},{"method":"POST","path":"/api/ext/v1/arbitrage/proposals/:id/reject","scope":"arbitrage:write","desc":"Billy-Vorschlag ablehnen."}]},{"id":"accounting","label":"Buchhaltung","description":"Rechnungs-/Buchhaltungs-Cockpit (nur lesend).","scopes":["accounting:read"],"endpoints":[{"method":"GET","path":"/api/ext/v1/accounting/overview","scope":"accounting:read","desc":"AR/AP, Periode, Kalenderblatt."}]}],"token_ttl_s":3600,"token_endpoint":"/api/platform/token","authorization_endpoint":"/api/platform/authorize","grant_types":["client_credentials","authorization_code","refresh_token"],"code_challenge_methods":["S256"],"pkce_required":true,"conventions":{"token_lifecycle":{"access_token_ttl_s":3600,"refresh_token_ttl_s":2592000,"auth_code_ttl_s":300,"refresh_rotates":true,"revoke_invalidates":["access","refresh","codes"],"pkce":"S256 verpflichtend (plain abgelehnt)"},"rate_limit":{"enforced":true,"per_app_per_min":120,"token_endpoint_per_min":60,"token_endpoint_ip_per_min":120,"headers":["X-RateLimit-Limit","X-RateLimit-Remaining","X-RateLimit-Reset","Retry-After"],"note":"Harte Ratenbegrenzung: 120 Anfragen/min je App auf der Ext-API, 60/min je Client am Token-Endpoint (429 + Retry-After; via EXT_RATE_LIMIT_PER_MIN / EXT_TOKEN_RATE_LIMIT_PER_MIN uebersteuerbar); zusaetzliches IP-Prelimit am Token-Endpoint (120/min je IP, EXT_TOKEN_IP_RATE_LIMIT_PER_MIN) gegen rotierende Client-IDs."},"pagination":{"style":"limit","default_limit":20,"note":"Listen-Endpunkte akzeptieren ?limit=; Standard 20, keine Cursor."},"error_format":{"shape":"{ error, detail? }","codes":{"400":["unsupported_grant_type","invalid_scope","invalid_grant"],"401":["unauthorized","invalid_token","expired_token","revoked_client","invalid_client"],"403":["insufficient_scope","module_disabled"],"429":["rate_limited"]}}}}