Repository navigation
Web API
The remote's web server (port 8080) is also an API: the builder, the Home Assistant integration and the Astrion Config Manager add-on all use it. This page is the contract for tools that read or write a remote's dashboard.
🔒 The API has no authentication: anyone on your network can use it. Turn Web page off in Settings › Web configuration once you're done setting up if that matters to you.
GET /info
{ "id": "astrion-…", "name": "Living room", "manufacturer": "…", "model": "…", "android": "8.1.0",
"version": "1.3.1", "versionCode": …, "webhook": true }version can end with -beta. To test for a feature, prefer trying the route (a 404 means "not in this version") over comparing version strings.
| Route | Does |
|---|---|
GET /dashboard.json |
The current dashboard. 404 with "No dashboard.json yet" on a new remote. |
POST /dashboard.json |
Replaces it and reloads the remote. multipart/form-data, field file (the JSON), optional field note (1.3.0+). |
Reply to POST /dashboard.json: 200 with a short HTML page (meant for browsers). Since 1.3.1 it also carries the header:
X-Astrion-Version-Id: 20261018-151600
the id of the version this push created in the remote's history. Absent before 1.3.1, or if the history couldn't be written. Read it from a server (the add-on, a script): the remote sends no CORS headers here, so a web page on another address can't see it.
Notes: up to 200 characters, longer ones are cut. Shown in the builder's 🕘 history. Tools should say who they are, e.g. ACM v42 · Before TV change.
The remote keeps every saved version in /sdcard/astrion/history: the last 30, plus pinned ones, each a full copy.
| Route | Does |
|---|---|
GET /history |
{"versions":[…]}, newest first (see below). |
GET /history/<id> |
That version's content, as a file download. |
POST /history/restore |
id → writes that version back and reloads the remote. Recorded as a new version (reason: "restore"). |
POST /history/pin |
id, pinned=true|false → a pinned version is never deleted automatically. |
POST /history/note |
id, note → sets or replaces the note. |
POST /history/delete |
id → removes that version. |
POST parameters are form fields (application/x-www-form-urlencoded or multipart/form-data). A malformed id → 400, an unknown one → 404.
A version in GET /history:
{ "id": "20261018-151600", "time": 1792329360000, "reason": "save", "note": "ACM v42 · Before TV change",
"pinned": false, "restoredFrom": "", "size": 18421, "pages": 6, "cards": 31 }| Field | Meaning |
|---|---|
id |
yyyyMMdd-HHmmss, plus -1, -2… if two versions share a second. Sorts in time order as text. |
time |
Milliseconds since 1970 (UTC). |
reason |
save: sent by POST /dashboard.json (builder, web page, tools) · restore: by POST /history/restore · outside: the file had changed some other way (remote Settings, a file copied by hand). |
restoredFrom |
For restore: the id it came from. Empty otherwise. |
size, pages, cards
|
Bytes, number of pages, number of cards. |
A change made outside the web page is only recorded at the next save or restore, just before the new version. Until then it is in dashboard.json but not in the history.
So, to explain why a remote's dashboard changed: compare GET /dashboard.json with the newest version's content. Same content → the newest version's reason and note say what happened. Different → it was changed outside the web page and isn't in the history yet.
| Route | Does |
|---|---|
GET /weather-search?q=<town or postcode>&lang=fr |
Place search for the built-in weather, done by the remote through Open-Meteo: {"results":[{"name","admin1","country","latitude","longitude"}]}, at most 8. 400 if q is shorter than 2 characters, 503 if the remote can't reach Open-Meteo. |
With a weather block in dashboard.json (name, latitude, longitude, optional model: auto/meteofrance, unit: celsius/fahrenheit), the remote publishes the entity weather.astrion: it appears in GET /ha-states like a Home Assistant weather entity (state = condition, temperature, humidity, wind_speed, attribution).
Links into the builder served by the remote, http://<remote-ip>:8080/builder/…:
| Link | Opens |
|---|---|
/builder/#history |
Version history (1.3.0+) |
/builder/#page=<name> |
That page |
/builder/#page=<name>&card=<index> |
That card's form, index counted from 0 in the page |
/builder/#activity=<id> |
That Activity's wizard |
/builder/#hotkeys |
The physical keys section |
-
<name>is URL-encoded (encodeURIComponentin JavaScript,urllib.parse.quote(name, safe='')in Python):#page=Living%20room,#page=TV%20%2B%20Ampli. A bare+would read as a space. - The builder first loads the remote's dashboard, then opens the target.
- An unknown page, card or Activity → the builder just opens normally.
- Changing the hash of a builder tab that's already open works too: it closes what's open and goes to the new target.
- Open these links in a new tab, not in an iframe: from a page served over HTTPS (Home Assistant with SSL, Nabu Casa) the browser blocks an
http://frame, and they only work on the home network.
🚀 Getting started
- Coming from Harmony
- Installation
- The remote's web page
- The builder
- Updates & beta
- FAQ & troubleshooting
🧩 Cards
- Light · Cover · Switch
- Climate · Fan
- Media player · Source select · Speaker group
- Select · Monitor
- Camera · Vacuum · Clock & weather
- Plex · Picture elements
- Title · Row
- Button grid · Scene grid
- TV remote / Apple TV remote
🎮 Control
- Physical keys & hotkeys
- Activities
- Harmony Hub
- IR devices & IR database
- IR extenders
- Apple TV (direct)
🏡 Home Assistant
🔋 The remote
📄 Reference
- dashboard.json guide: EN · FR · DE · IT · ES
- Recipes
- Translating Astrion
- Web API (for tools)