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

# Diagnose a Charger That Is Not Charging

> One read of the charger tells you why a connected car takes no power, and what to tell the driver.

## Overview

The car is connected. No power flows. The ticket says the charger is broken.

Most of the time it is not. One read of the charger answers the ticket, and two fields carry the answer. **`activeControlMode` names the control regime that holds the charger.** **`notChargingReason` names what stops the current.** Read them in that order. A charger under a strategy is usually correct and quiet, not broken.

These are the fields that close the ticket.

| Field               | What it tells you                                                                                                                                               |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`            | `available`, `charging`, `discharging`, `scheduled`, `error`, or `offline`.                                                                                     |
| `isConnected`       | Whether a vehicle is connected to the charger.                                                                                                                  |
| `isCharging`        | Whether the charger delivers power to the vehicle right now.                                                                                                    |
| `currentPower`      | Power in kW, signed. Positive into the car, negative out of it. Absent on a charger whose API reports no power at all, which is not the same as a reported `0`. |
| `notChargingReason` | Why a connected car takes no power. Absent while the car charges, and absent while nothing is connected.                                                        |
| `activeControlMode` | The control regime the charger reports. Absent on a charger that reports none.                                                                                  |

## Step 1: Read the charger

One GET carries every field the triage needs.

```bash theme={null}
curl -X GET https://api.amps.ai/ev-charger/device_ev_001 \
  -H "x-api-key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx"
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device_ev_001",
    "vendor": "example_vendor_a",
    "sync": { "available": true, "lastPulledAt": "2026-08-12T19:04:00.000Z" },
    "metadata": { "model": "7kW AC Charger", "source": "live" },
    "state": {
      "status": "available",
      "isConnected": true,
      "isCharging": false,
      "currentPower": 0,
      "maxCurrent": 32,
      "powerRateLimit": 7.4,
      "sessionEnergy": 0,
      "phases": 1,
      "voltage": 230,
      "notChargingReason": "authorization"
    },
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "sessions": true,
    "vehicle": null,
    "lastAction": null,
    "currentSchedule": null
  },
  "meta": {
    "requestId": "req_4kP2nHtR",
    "environment": "live",
    "timestamp": "2026-08-12T19:04:00.000Z",
    "latencyMs": 24
  }
}
```

`isConnected` is `true` and `isCharging` is `false`, so a car sits on the cable and takes nothing. This charger reports no `activeControlMode` at all, so no strategy explains the pause and `notChargingReason` is the answer. It reads `authorization`. Tell the driver to approve the session. Do not send an engineer.

## Step 2: Check the control regime first

Read `activeControlMode` before anything else. A charger that runs a strategy picks its own hours, so a quiet charger is often a charger that does its job.

Under `auto.charge_tariff` the charger waits for the cheap hours of the tariff the home owner configured. Under `auto.charge_surplus_only` it waits for surplus from the solar array, and it pauses whenever that surplus runs out. Under `auto.charge_surplus_first` it takes the surplus first, then draws the remainder from the grid.

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device_ev_001",
    "vendor": "example_vendor_a",
    "sync": { "available": true, "lastPulledAt": "2026-08-12T19:31:00.000Z" },
    "metadata": { "model": "7kW AC Charger", "source": "live" },
    "state": {
      "status": "scheduled",
      "isConnected": true,
      "isCharging": false,
      "currentPower": 0,
      "maxCurrent": 32,
      "powerRateLimit": 7.4,
      "phases": 1,
      "voltage": 230,
      "notChargingReason": "schedule",
      "activeControlMode": "auto.charge_tariff"
    },
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "sessions": true,
    "vehicle": null,
    "lastAction": null,
    "currentSchedule": null
  },
  "meta": {
    "requestId": "req_5mQ3pJuS",
    "environment": "live",
    "timestamp": "2026-08-12T19:31:00.000Z",
    "latencyMs": 19
  }
}
```

Same stillness, opposite meaning. The charger runs `auto.charge_tariff` and holds for a cheap hour. This is the strategy at work. Show the driver "waiting for off-peak", never "not charging", and never raise a fault.

`activeControlMode` is absent on a charger that does not report its regime, as in Step 1. Absence is not a value, so test that the key exists before you read it. If no strategy explains the pause, go to `notChargingReason`.

## Step 3: Read the reason

`notChargingReason` takes six values. Each one sends you to a different place.

| Value             | What the charger means                                            | What you tell the driver                                                     |
| ----------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `vehicle`         | The car declined the charge, or the car has finished.             | Look at the car. Check its own charge limit.                                 |
| `charger`         | The charger limits or curtails the current.                       | A limit or a fault on the charger holds it. Check the charger.               |
| `load_management` | A site power share holds the charge. Other loads have the supply. | The site divides its supply. The charge continues when capacity frees. Wait. |
| `authorization`   | The charger waits for an RFID card or an approval in the app.     | Approve the session in the app, or present the card.                         |
| `schedule`        | The charger's own schedule vetoes the charge right now.           | A schedule on the charger holds it. Change it in the brand's app.            |
| `unknown`         | The charger reports a pause and does not name the cause.          | The charge is on hold. Name no cause.                                        |

Two of these are easy to read wrongly, and both change the answer you give.

**`vehicle` points at the car, not at the charger.** The charger reports that the car declined the charge or finished it. The hardware on the wall is healthy, so a charger swap fixes nothing. Send the driver to the car and to the car's charge limit.

**An absent reason is not `unknown`.** `unknown` means the charger reports a pause whose cause it does not name. You can honestly tell the driver the charge is on hold. An absent key means the brand reports no reason at all, so you know nothing and must claim nothing. One is a hold you can report. The other is silence.

## Step 4: Turn the read into an answer

Branch on the control regime, then on the reason. Handle the absent key before you read the value.

```javascript theme={null}
const { state } = (await res.json()).data;

if (state.isCharging) return "Charging";
if (!state.isConnected) return "Plug the car in";
if (state.activeControlMode?.startsWith("auto.")) return "Waiting for the right moment";
if (!("notChargingReason" in state)) return "Paused. The charger gives no reason.";

const advice = {
  authorization: "Approve the session in the app, or present your card.",
  load_management: "The site shares its supply. The charge continues when capacity frees.",
  schedule: "A schedule on the charger holds it. Check the charger's app.",
  charger: "The charger limits the current. Check the charger.",
  vehicle: "The car stopped the charge. Check the car's charge limit.",
  unknown: "The charge is on hold. The charger does not say why.",
};

return advice[state.notChargingReason];
```

`authorization` and `schedule` both clear in the brand's app, and the driver clears them in seconds. `vehicle` clears at the car. `load_management` clears by itself when site capacity frees. `charger` is the only value that can need an engineer, and it is the rarest of the six.

## At push time

Triage runs after the fact. The same vocabulary reaches you earlier, at the moment you send a command.

An accepted `POST /ev-charger/{deviceId}` returns 202, and the response can carry a `warnings` array beside the action. Each entry names one condition the charger reported when you submitted the command.

```json theme={null}
{
  "code": "vehicle_not_connected",
  "message": "No vehicle is connected to the charger. The command is accepted and takes effect when a vehicle plugs in.",
  "observedAt": "2026-08-12T19:04:00.000Z"
}
```

Two codes appear, and both mirror a reason from the table above. `vehicle_not_connected` means no car is plugged in. `awaiting_authorization` means the charge waits for approval in the manufacturer's app.

A warning is not a rejection. The command is accepted and armed, and it applies the moment the condition clears, so plugging the car in starts the charge you already asked for. The warning tells you only that the charge will not start yet, which is what you show the driver instead of a spinner that never resolves.

The property is absent when nothing blocks the command, so read its absence as no known obstacle at submission time. Warnings describe an immediate push. A push carrying `start` is armed against a state the charger cannot report yet, so it carries none.

## What next

<CardGroup cols={2}>
  <Card title="Smart charging modes" icon="bolt" href="/guides/cookbook/ev-smart-charging">
    The strategies behind an `activeControlMode` that starts with `auto.`.
  </Card>

  <Card title="EV charger cheat sheet" icon="list-checks" href="/reference/ev-charger-cheat-sheet">
    The whole charger surface in one page.
  </Card>

  <Card title="Device state" icon="activity" href="/concepts/device-state">
    Why a reading is absent instead of zero.
  </Card>
</CardGroup>

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "HowTo",
"name": "Diagnose a Charger That Is Not Charging",
"description": "One read of the charger tells you why a connected car takes no power, and what to tell the driver.",
"step": [
{ "@type": "HowToStep", "name": "Step 1: Read the charger", "position": 1 },
{ "@type": "HowToStep", "name": "Step 2: Check the control regime first", "position": 2 },
{ "@type": "HowToStep", "name": "Step 3: Read the reason", "position": 3 },
{ "@type": "HowToStep", "name": "Step 4: Turn the read into an answer", "position": 4 }
]
})}}
/>
