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

# Discharge During a Peak Window

> Force-discharge a battery during a peak-demand window with a lower SoC limit. Curl, JSON response, follow-up state poll.

## Overview

To sell stored energy during peak-rate hours, or shave household load during a demand event, push a windowed `discharge`. The body mirrors a windowed charge: `command: "discharge"`, `start`, `end`, and a `target` that names the lower SoC at which discharging stops.

Confirm the device supports windowed discharge before pushing. Look for `windowed` in `commands.discharge.execution`.

## Step 1: Check capability before pushing

Every response is wrapped in `{ success, data, meta }`; the device sits under `data`.

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

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device_abc123",
    "vendor": "foxess",
    "sync": { "available": true, "lastPulledAt": "2026-05-08T08:29:48.000Z" },
    "metadata": { "model": "FoxESS H1-5.0-E", "source": "projection" },
    "state": {
      "status": "idle",
      "capacity": 10.4,
      "level": 92,
      "chargeRate": 0,
      "dischargeLimit": 10,
      "currentMode": "auto.balance"
    },
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "commands": {
      "discharge": {
        "parameters": {
          "target": { "unit": "percent", "min": 10, "max": 100 },
          "power": { "unit": "kw", "min": 0, "max": 5 },
          "reserve": { "unit": "percent", "min": 0, "max": 100 }
        },
        "execution": ["windowed"]
      }
    },
    "lastAction": null,
    "currentSchedule": null
  },
  "meta": {
    "requestId": "req_7qI1eQtH",
    "environment": "sandbox",
    "timestamp": "2026-05-08T08:29:48.000Z",
    "latencyMs": 27
  }
}
```

For a discharge, `target` is the lower bound: discharging stops at this level. `reserve` is a second floor that protects against full depletion if the window overruns.

## Step 2: Push the windowed discharge

Discharge from late afternoon into the early evening, stopping at 30%.

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl -X POST https://api.amps.ai/battery/device_abc123 \
      -H "x-api-key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{
        "action": {
          "command": "discharge",
          "start": "2026-05-08T16:00:00",
          "end": "2026-05-08T19:00:00",
          "parameters": {
            "target": { "value": 30, "unit": "percent" },
            "power": { "value": 5, "unit": "kw" },
            "reserve": { "value": 20, "unit": "percent" }
          }
        }
      }'
    ```
  </Tab>

  <Tab title="Node">
    ```javascript theme={null}
    const res = await fetch("https://api.amps.ai/battery/device_abc123", {
      method: "POST",
      headers: {
        "x-api-key": process.env.AMPS_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        action: {
          command: "discharge",
          start: "2026-05-08T16:00:00",
          end: "2026-05-08T19:00:00",
          parameters: {
            target: { value: 30, unit: "percent" },
            power: { value: 5, unit: "kw" },
            reserve: { value: 20, unit: "percent" },
          },
        },
      }),
    });

    const body = await res.json();              // { success, data, meta }
    const { id, deviceId, links } = body.data;
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os, requests

    res = requests.post(
        "https://api.amps.ai/battery/device_abc123",
        headers={
            "x-api-key": os.environ["AMPS_API_KEY"],
            "Content-Type": "application/json",
        },
        json={
            "action": {
                "command": "discharge",
                "start": "2026-05-08T16:00:00",
                "end": "2026-05-08T19:00:00",
                "parameters": {
                    "target": {"value": 30, "unit": "percent"},
                    "power": {"value": 5, "unit": "kw"},
                    "reserve": {"value": 20, "unit": "percent"},
                },
            }
        },
    )
    body = res.json()                           # { success, data, meta }
    action_id = body["data"]["id"]
    device_id = body["data"]["deviceId"]
    ```
  </Tab>
</Tabs>

You get back the scheduled action under `data`.

```json theme={null}
{
  "success": true,
  "data": {
    "id": "act_pending_007",
    "deviceId": "device_abc123",
    "deviceType": "battery",
    "command": "discharge",
    "parameters": {
      "target": { "value": 30, "unit": "percent" },
      "power": { "value": 5, "unit": "kw" },
      "reserve": { "value": 20, "unit": "percent" }
    },
    "state": "scheduled",
    "createdAt": "2026-05-08T08:30:00.000Z",
    "start": "2026-05-08T16:00:00.000Z",
    "end": "2026-05-08T19:00:00.000Z",
    "links": { "self": "/actions/act_pending_007" }
  },
  "meta": {
    "requestId": "req_8rJ2fSvI",
    "environment": "sandbox",
    "timestamp": "2026-05-08T08:30:00.000Z",
    "latencyMs": 88
  }
}
```

## Step 3: Confirm the window opened

After `start`, read the action to confirm dispatch. `acknowledgedAt` is the moment the OEM accepted the write.

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

```json theme={null}
{
  "success": true,
  "data": {
    "id": "act_pending_007",
    "deviceId": "device_abc123",
    "deviceType": "battery",
    "command": "discharge",
    "parameters": {
      "target": { "value": 30, "unit": "percent" },
      "power": { "value": 5, "unit": "kw" },
      "reserve": { "value": 20, "unit": "percent" }
    },
    "state": "acknowledged",
    "result": null,
    "errorCode": null,
    "errorMessage": null,
    "createdAt": "2026-05-08T08:30:00.000Z",
    "updatedAt": "2026-05-08T16:00:02.000Z",
    "acknowledgedAt": "2026-05-08T16:00:02.000Z",
    "completedAt": null,
    "start": "2026-05-08T16:00:00.000Z",
    "end": "2026-05-08T19:00:00.000Z",
    "links": { "self": "/actions/act_pending_007" }
  },
  "meta": {
    "requestId": "req_9sK3gTwJ",
    "environment": "sandbox",
    "timestamp": "2026-05-08T16:00:03.000Z",
    "latencyMs": 18
  }
}
```

A second `GET /battery/device_abc123` confirms live state. While the window is active, `data.state.status` reports `discharging` and `data.state.chargeRate` is negative.

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device_abc123",
    "vendor": "foxess",
    "sync": { "available": true, "lastPulledAt": "2026-05-08T16:30:11.000Z" },
    "metadata": { "model": "FoxESS H1-5.0-E", "source": "projection" },
    "state": {
      "status": "discharging",
      "level": 78,
      "chargeRate": -4.8,
      "capacity": 10.4,
      "dischargeLimit": 10,
      "currentMode": "discharge"
    },
    "conflictStrategies": ["cancel_and_replace", "queue_after"],
    "lastAction": {
      "id": "act_pending_007",
      "command": "discharge",
      "state": "acknowledged",
      "createdAt": "2026-05-08T08:30:00.000Z",
      "updatedAt": "2026-05-08T16:00:02.000Z",
      "errorCode": null,
      "errorMessage": null,
      "links": { "self": "/actions/act_pending_007" }
    },
    "currentSchedule": null
  },
  "meta": { "requestId": "req_0tL4hUxK", "environment": "sandbox", "timestamp": "2026-05-08T16:30:11.000Z", "latencyMs": 41 }
}
```

At `end`, the action transitions to `completed` and the battery reverts to `idle`, holding the level the window left behind. The window closes, the device stops moving energy. To resume self-management, push `auto.balance` (or any other standing mode) next.

## What next

<CardGroup cols={2}>
  <Card title="Schedule a charge for later" icon="moon" href="/guides/cookbook/schedule-charge-later">
    The mirrored recipe for cheap-rate charging.
  </Card>

  <Card title="Subscribe to webhooks" icon="webhook" href="/guides/cookbook/subscribe-webhooks">
    Get push.completed events when the window closes.
  </Card>

  <Card title="Handle conflicts" icon="triangle-alert" href="/guides/cookbook/handle-conflict">
    What to do when a colliding action is in flight.
  </Card>

  <Card title="Canonical actions" icon="book-open" href="/concepts/canonical-actions">
    The semantic model behind charge, discharge, and auto.
  </Card>
</CardGroup>

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "HowTo",
"name": "Discharge During a Peak Window",
"description": "Force-discharge a battery during a peak-demand window with a lower SoC limit. Curl, JSON response, follow-up state poll.",
"step": [
{
  "@type": "HowToStep",
  "name": "Step 1: Check capability before pushing",
  "position": 1
},
{
  "@type": "HowToStep",
  "name": "Step 2: Push the windowed discharge",
  "position": 2
},
{
  "@type": "HowToStep",
  "name": "Step 3: Confirm the window opened",
  "position": 3
}
]
})}}
/>
