> ## 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.

# Pull

> Read a device's state, list devices, and understand how fresh the data is.

Read what a device is doing now, what it can do, and what Amps last told it to do. The read shape is the same for every device type; only the `state` fields change.

## Read a device

```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",
    "vendor": "example_vendor_a",
    "sync": { "available": true, "lastPulledAt": "2026-06-01T10:14:23.000Z" },
    "metadata": { "model": "Hybrid 5kWh", "source": "cache", "cacheType": "normal" },
    "state": {
      "status": "charging",
      "level": 50,
      "capacity": 10.4,
      "chargeRate": 2.4,
      "dischargeLimit": 10,
      "currentMode": "charge"
    },
    "commands": {
      "charge": {
        "parameters": { "target": { "unit": "percent", "min": 0, "max": 100 } },
        "execution": ["immediate", "scheduled", "windowed"]
      }
    },
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "settings": { "discharge_floor": { "value": 10, "unit": "percent", "min": 0, "max": 100 } },
    "lastAction": {
      "id": "action_FoRvdqounP",
      "command": "charge",
      "state": "completed",
      "links": { "self": "/actions/action_FoRvdqounP" }
    },
    "currentSchedule": null
  }
}
```

The same route exists for every type: `/battery`, `/ev-charger`, `/hvac`, `/solar-inverter`, `/vehicle`.

| Field | |
| - | - |
| `state` | What the device is doing now. Fields per type are [listed below](#state-fields-by-device-type). |
| `sync` | `available` is `false` when the reading is a stored fallback. `lastPulledAt` is when the reading was taken from the device. |
| `metadata` | `model`, plus where the reading came from. See [Freshness](#freshness). |
| `commands`, `conflictStrategies` | What the device accepts. See [Capabilities](/guides/capabilities). |
| `settings` | Persistent configuration with current values. See [Settings](/guides/capabilities/settings). Batteries and EV chargers only. |
| `sessions` | EV chargers only. `true` when the charger reports charging-session history at `/ev-charger/{deviceId}/sessions`. |
| `lastAction` | Summary of the most recent action you sent to this device. `null` until the first one. |
| `currentSchedule` | Always `null` for now. |

Solar inverters and vehicles are read-only. Their reads carry `id`, `vendor`, `sync`, `metadata`, and `state`, and nothing else.

## What the device is doing vs what it was told

`state.status` is what the battery is doing. `state.currentMode` is the command it's running. They can differ: a `charge` whose target is already met reads `status: "idle"`, `currentMode: "charge"`, `chargeRate: 0`. EV chargers report the same split with `isCharging` and `activeControlMode`.

Compare `state` with `lastAction` to spot changes made outside Amps, such as the homeowner switching mode in the manufacturer's app.

## `lastAction`

A summary for rendering a device card in one call. For parameters and the full result, follow `links.self` to [`GET /actions/{id}`](/guides/push).

```json theme={null}
{
  "id": "action_FoRvdqounP",
  "command": "charge",
  "state": "failed",
  "createdAt": "2026-06-01T09:15:00.000Z",
  "updatedAt": "2026-06-01T09:15:32.000Z",
  "errorCode": "DEVICE_OFFLINE",
  "errorMessage": "The device is currently offline at the manufacturer.",
  "links": { "self": "/actions/action_FoRvdqounP" }
}
```

`updatedAt` is the last state change. `errorCode` and `errorMessage` are `null` unless `state` is `failed`. A just-sent action can take a moment to appear here, so read it by id if you need its state straight after a push.

## Freshness

Live reads are cached. `metadata.source` tells you where a reading came from.

| `metadata.source` | Meaning | `sync.available` |
| - | - | - |
| `cache` | A recent reading. Up to 15 minutes old, or 1 minute with `?expedite=true`. `cacheType` says which. | `true` |
| `live` | Read from the device during this request. | `true` |
| `fallback` | The device couldn't be reached, so this is the last stored reading. Check `sync.lastPulledAt`. | `false` |
| `projection` | Simulated sandbox state. See [Sandbox](#sandbox). | `true` |

For fresher data, add `?expedite=true`. It returns a reading no more than a minute old, calling the manufacturer if needed. Use it sparingly.

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

A completed push doesn't refresh the cache. To react to a command, use the [`push.completed` webhook](/guides/webhooks/events), then read with `?expedite=true` if you need the new state.

In live, `settings` is included when the reading comes from the device (`source: "live"`) and omitted on cached and fallback readings. A setting the device reports in an unusable form, or outside its declared range, is left out rather than shown.

When Amps has temporarily paused reads for a manufacturer, you get the last stored reading with `metadata.degraded: true`, or `503 CAPABILITY_PAUSED`. Retry with backoff.

If the device is offline or unknown at the manufacturer, the read returns an error (`DEVICE_OFFLINE`, `DEVICE_NOT_FOUND`) instead of stale data. See [Error codes](/guides/error-handling/error-codes).

## List devices

```bash theme={null}
curl "https://api.amps.ai/battery?userId=user_abc123&limit=20&offset=0" \
  -H "x-api-key: $AMPS_API_KEY"
```

```json theme={null}
{
  "success": true,
  "data": {
    "items": [{ "id": "device_abc123", "state": { "status": "idle", "level": 67 }, "lastAction": null }],
    "pagination": { "limit": 20, "offset": 0, "total": 1, "hasMore": false }
  }
}
```

| Query | |
| - | - |
| `userId` | Only devices linked by this end user. |
| `limit` | 1 to 50. Default 10. |
| `offset` | Default 0. |

List entries carry the last stored reading, `commands`, `conflictStrategies`, and `lastAction`, but not `settings`. For current state, read the device by id.

## Sandbox

Sandbox devices are simulated. Batteries, EV chargers, and thermostats report `source: "projection"`, and their state follows the commands you send: push `charge` and the next read shows `status: "charging"` with `level` rising toward the target. No cache, no waiting.

* Values in motion change between reads. Compare against the command you sent, not an exact earlier number.
* A windowed command is active between `start` and `end`, then the device goes idle and holds where the window left it.
* With no commands, devices follow a daily pattern on UTC time, for example batteries charge around midday UTC.

Solar inverters and vehicles follow the UTC daily pattern only, since they take no commands. Their reads report `cache` or `live`.

## State fields by device type

### Battery

| Field | Unit | Meaning |
| - | - | - |
| `status` | | `charging`, `discharging`, `idle`, or `standby`. |
| `level` | percent | State of charge, 0 to 100. |
| `capacity` | kWh | Total capacity. |
| `chargeRate` | kW | Current charge rate. Negative when discharging. |
| `dischargeLimit` | percent | Discharge limit. |
| `currentMode` | | The command the battery is running, such as `charge` or `auto.balance`. Omitted when the mode has no canonical equivalent. |

### EV charger

| Field | Unit | Meaning |
| - | - | - |
| `status` | | `available`, `charging`, `discharging`, `scheduled`, `error`, or `offline`. |
| `isConnected` | | A vehicle is plugged in. |
| `isCharging` | | The charger is delivering power to the vehicle now. |
| `currentPower` | kW | Current power. Negative when exporting from the vehicle. |
| `maxCurrent` | A | Maximum current the charger can deliver. |
| `powerRateLimit` | kW | Configured maximum charging power. |
| `sessionEnergy` | kWh | Energy delivered in the current session. |
| `phases` | | Supply phases in use, 1 to 3. |
| `voltage` | V | Supply voltage. |
| `notChargingReason` | | Why a plugged-in vehicle isn't charging: `vehicle`, `target_reached`, `charger`, `load_management`, `authorization`, `schedule`, or `unknown`. |
| `activeControlMode` | | The command the charger is running, such as `charge` or `auto.charge_tariff`. |

Only `status`, `isConnected`, and `isCharging` are always present. The rest are omitted when the charger doesn't report them, never sent as zero.

### HVAC

| Field | Unit | Meaning |
| - | - | - |
| `temperature` | °C | Current temperature. |
| `active` | | Heating or cooling right now. |
| `heatSetpoint` | °C | Heats below this. |
| `coolSetpoint` | °C | Cools above this. |
| `mode` | | `heat`, `cool`, `auto`, or `off`. |
| `holdType` | | `permanent` when a fixed setpoint overrides the device's own program, `schedule` when it's following it. |

### Solar inverter

| Field | Unit | Meaning |
| - | - | - |
| `status` | | `producing`, `idle`, `night_mode`, `error`, or `offline`. |
| `producing` | | Producing power now. |
| `currentPower` | kW | Current AC output. |
| `energyTotal` | kWh | Lifetime production. |

### Vehicle

| Field | Unit | Meaning |
| - | - | - |
| `batteryLevel` | percent | State of charge, 0 to 100. |
| `range` | miles | Estimated remaining range. |
| `plugged` | | Plugged in to a charger. |
| `charging` | | Drawing charge now. |
| `fullyCharged` | | Reached `chargeLimit`. |
| `batteryCapacity` | kWh | Usable capacity. |
| `chargeLimit` | percent | Configured charge limit. |
| `chargeRate` | kW | Current charge rate. Negative when discharging. |
| `chargeTimeRemaining` | minutes | Time to reach `chargeLimit`. |
| `maxCurrent` | A | Maximum current the vehicle accepts. |

## Next steps

<CardGroup cols={2}>
  <Card title="Capabilities" icon="list-check" href="/guides/capabilities">
    Read `commands` to build a valid push.
  </Card>

  <Card title="Push" icon="arrow-up" href="/guides/push">
    Send commands and track actions.
  </Card>

  <Card title="Webhooks" icon="bell" href="/guides/webhooks">
    React to completed actions instead of polling.
  </Card>

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


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