Configure a remote's buttons through the API
A remote’s button configuration belongs to the remote itself. You read and write the remote’s own record through the API, not a routine, and the configuration lives with the remote rather than in the routines list. Each configured cell is one button plus one gesture, and each cell stores an ordered sequence of steps. When the hub runs a cell, it records that run separately from routine runs. Local hub actions keep working during a cloud outage; if a step depends on a cloud provider, that step still depends on the provider and network being available.
What this endpoint returns
Section titled “What this endpoint returns”GET /endpoints/:endpointId/buttons returns a view of the remote’s own record. The response includes:
endpointIdlayoutcellsstalewhen the remote used to report cells it can no longer addressunrunnablewhen the hub cannot be left to run one or more configured cells
Use layout to learn the remote’s actual shape instead of assuming a grid. layout.count is how many buttons the remote has, and layout.gestures lists the gestures it can actually send. cells is keyed as "<button>:<gesture>". Button numbers start at 1, and the only gestures are single, double, triple, long, and hold.
An empty cells object means nothing is configured yet. That is a valid state, not an error.
Required access
Section titled “Required access”Both read and write require a household session. Application credentials and delegated surface credentials are refused for these routes. Use the authenticated API for the selected tenant and home, and respect the permission the server returns.
Read access needs permission to view the home. Write access needs permission to manage it. Household permissions are narrower than staff permissions, so a user who can view a home may still be unable to change button bindings.
Reading button bindings
Section titled “Reading button bindings”Read the current bindings with GET /endpoints/:endpointId/buttons. The response shows the current grid, the configured cells, and any stale cells that no longer fit the remote’s current button count or gesture set.
A stale cell is one that was configured before the remote reported a smaller or different layout. The client should show stale cells so the household can remove them. A save that keeps one is refused.
The unrunnable list names cells the hub cannot be left to run. Keep those cells editable in the UI, but show why the hub cannot run them.
Writing button bindings
Section titled “Writing button bindings”Use PUT /endpoints/:endpointId/buttons to replace the whole record. Send the whole cells map back, not a partial update. A cell left out is no longer bound.
Each cell holds an ordered sequence of steps. A step may be one of four things in the editor workflow:
- a device command
- a room action
- a wait
- an existing routine run by id
Run a routine calls the same hub routine as Run now even when it is disabled or its Only if conditions are false, and the called routine’s cloud actions use that routine’s own identity and step indexes.
The server refuses invalid cells with messages that name the button, gesture, and step. Typical refusals include cells the remote cannot send, routines not in this home, devices not in this home, rooms not in this home, and non-remote devices where a button-driven step expects an endpoint. A write conflict means the remote changed while the save was in progress; read the record again and retry.
Saving also removes any stale presses the remote can no longer send. If the resulting hub set would exceed the hub’s accepted size, the write is refused instead of being pushed.
What the hub does
Section titled “What the hub does”The home’s hub holds the record, matches the press, and runs the steps itself. That means a configured press continues to work while the internet is unavailable, as long as the step does not need a cloud provider.
A press produces a thing.state event for the remote, carrying the button and gesture readings when the remote reports them. The remote is pressed by hand; no request presses it, and you should not synthesize a press to refresh state.
The hub also records the cell run as one buttons.run command-history row against the hub. That is separate from any RoutineRun created by a routine step inside the cell.
Step behavior and limits
Section titled “Step behavior and limits”A cell can contain at least one step and at most 30. The gestures are fixed to the five-word set above. Each configured cell is keyed by "<button>:<gesture>".
A cell may include an existing routine by id. That routine must already belong to the home. If the routine is cloud-dependent, the cloud path must be available for that step to complete.
A configured press that the hub can no longer run is shown as unrunnable. A press that the remote can no longer send is shown as stale. Keep those two cases separate when you build the editor.
Practical workflow
Section titled “Practical workflow”- Read
GET /endpoints/:endpointId/buttons. - Check
layout.countandlayout.gestures. - Edit the whole
cellsmap. - Preserve bindings the client does not edit.
- Write the whole record back with
PUT /endpoints/:endpointId/buttons. - If the server reports a conflict, reread and retry.
Preserve settings fields the client does not edit, and do not infer supported actions from brand, model, cached state, or a successful request acknowledgement. Follow the server-returned permissions, availability, versions, and pending versus confirmed results.
Remote-button cell limits
Section titled “Remote-button cell limits”Direct remote-button cells retain 30 independent steps. Ordinary routine authoring remains 255 steps. Nonempty excludeThingIds on direct remote room actions is refused because it cannot be compiled safely. Existing saved routine ID call behavior remains unchanged.