> ## Documentation Index
> Fetch the complete documentation index at: https://docs.amps.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Capabilities

> Discover which commands, parameters, units, and timings a device accepts, and what happens when it can't do something.

Every device read tells you exactly what that device accepts. Read it once, then build a push that will validate.

## Where capabilities live

There's no separate endpoint. `commands`, `conflictStrategies`, and `settings` come back on the device read.

```bash theme={null}
curl https://api.amps.ai/battery/device_abc123 \
  -H "x-api-key: $AMPS_API_KEY"
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device_abc123",
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "commands": {
      "charge": {
        "parameters": {
          "target": { "unit": "percent", "min": 10, "max": 100 },
          "power": { "unit": "kw", "min": 0, "max": 5, "step": 0.1 }
        },
        "execution": ["immediate", "scheduled", "windowed"]
      },
      "auto.balance": {
        "parameters": {},
        "execution": ["immediate", "scheduled"]
      }
    }
  }
}
```

The read mirrors the push. `commands.charge.parameters.target` on the read becomes `action.parameters.target` on the [push](/guides/push), sent as `{ "value": 80, "unit": "percent" }`.

## Present means supported

If a key is present, the device supports it. If it's absent, the request is refused with `422 DEVICE_NOT_CAPABLE`. There is no `supported: false`.

| You send | Not offered on the read | Result |
| - | - | - |
| A command | Key missing from `commands` | `422 DEVICE_NOT_CAPABLE` |
| A parameter | Key missing from `parameters` | `422 DEVICE_NOT_CAPABLE` |
| A different unit | `unit` doesn't match | `422 DEVICE_NOT_CAPABLE` |
| A timing not in `execution` | | `422 DEVICE_NOT_CAPABLE` |
| An `onConflict` not in `conflictStrategies` | | `422 DEVICE_NOT_CAPABLE` |
| A value outside `min`/`max`, or off the `step` grid | | `422 PARAMETER_OUT_OF_RANGE` |

`parameters: {}` means the command is supported and takes no parameters.

## When a device can't do something

There are two different answers. Handle them differently.

| Response | Meaning | What to do |
| - | - | - |
| `422 DEVICE_NOT_CAPABLE` | The device doesn't offer this. Amps also leaves out any command or setting it holds back on a device. | Don't retry. Ask for something the read declares. |
| `503 CAPABILITY_PAUSED` | Amps has temporarily paused this capability. It stays on the read. | Keep it in your interface. Retry with backoff. |

An immediate `DEVICE_NOT_CAPABLE` can carry `details` naming the refused value and what the device offers, such as `deviceCapabilities.supportedModes`, `supportedExecution`, or `supportedStrategies`. A failed action carries only `errorCode` and `errorMessage`. See [Error codes](/guides/error-handling/error-codes).

## Units and bounds

Each parameter declares a `unit`, and optional `min`, `max`, and `step`. A missing bound is open-ended on that side. `step` is the increment a value must land on, counted from `min`.

Bounds are per device, not per type. Two batteries from different manufacturers can declare different ranges for the same parameter, so always read them from the device.

## Execution

`execution` lists the timings each command accepts. Details are in [Scheduling](/guides/scheduling).

| Token | Push shape |
| - | - |
| `immediate` | No `start` or `end` |
| `scheduled` | `start` only |
| `windowed` | `end`, with or without `start` |

Timings are per command. A battery can accept `charge` as windowed while `auto.balance` is immediate or scheduled only. `auto.*` commands are never windowed.

## Conflict strategies

`conflictStrategies` lists the `onConflict` values the device accepts when a new push collides with an active action. See [Conflicts](/guides/push/conflicts).

## Commands by device type

| Device type | Commands | Settings |
| - | - | - |
| Battery | `charge`, `discharge`, `idle`, `auto.balance`, `auto.reserve`, `auto.export` | Yes |
| EV charger | `charge`, `idle`, `auto.charge_tariff`, `auto.charge_surplus_only`, `auto.charge_surplus_first` | Yes |
| HVAC | `heat`, `cool`, `idle`, `auto.maintain`, `auto.schedule` | No |
| Solar inverter | None | No |
| Vehicle | None | No |

This is the full set per type. Each device declares the subset it supports.

## Read-only device types

Solar inverters and vehicles report state only. Their reads have no `commands`, `conflictStrategies`, or `settings`. A `POST` to `/solar-inverter/{deviceId}` or `/vehicle/{deviceId}` returns `405 METHOD_NOT_ALLOWED`, with the allowed methods in the `Allow` header.

## Live access and maturity

Which brands your end users can link in live depends on your account and each integration's maturity: experimental, beta, or general. General integrations are open to accounts enabled for live; earlier stages need early-access approval. Sandbox includes every brand. None of this appears on the device read, which shows only what the linked device offers.

<Callout icon="clock" color="#ED6D2C">
  **Coming soon.** Live control of thermostats. Sandbox supports every thermostat command.
</Callout>

## Next steps

<CardGroup cols={2}>
  <Card title="Push" icon="arrow-up" href="/guides/push">
    Turn a capability into a command.
  </Card>

  <Card title="Settings" icon="sliders" href="/guides/capabilities/settings">
    Read and change persistent device configuration.
  </Card>

  <Card title="Scheduling" icon="clock" href="/guides/scheduling">
    Run a command later or across a window.
  </Card>

  <Card title="Pull" icon="arrow-down" href="/guides/pull">
    Everything else on the device read.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.