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

# Scheduling

> Run a command later, or across a time window, in the device's local time.

Add `start` to run a command later, or `end` to run it across a window. Times are the device's local wall-clock time, so you never deal with UTC offsets.

## Timing

| Shape | Body | Action starts as | Behaviour |
| - | - | - | - |
| Immediate | No `start` or `end` | `acknowledged` | Runs now. |
| Scheduled | `start` | `scheduled` | Runs at `start`. |
| Windowed | `start` and `end` | `scheduled` | Runs from `start` until `end`. |
| Windowed from now | `end` only | `acknowledged` | Runs now until `end`. |

Each command lists the shapes it accepts in its `execution` array. Both windowed shapes need `windowed`. See [Capabilities](/guides/capabilities#execution).

## Schedule a window

```bash theme={null}
curl -X POST https://api.amps.ai/battery/device_abc123 \
  -H "x-api-key: $AMPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": {
      "command": "charge",
      "parameters": { "target": { "value": 90, "unit": "percent" } },
      "start": "2026-06-10T00:30:00",
      "end": "2026-06-10T04:30:00"
    }
  }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "id": "action_wd5ZqQtyBs",
    "command": "charge",
    "state": "scheduled"
  }
}
```

The battery charges from 00:30 to 04:30 where it's installed, wherever your servers are.

## Time format

Send `start` and `end` as local wall-clock time with no offset: `YYYY-MM-DDTHH:MM:SS`. Amps converts them using the device's timezone.

| Value | Accepted |
| - | - |
| `2026-06-10T22:00:00` | Yes |
| `2026-06-10T22:00:00Z` | No, `400 INVALID_REQUEST_BODY` |
| `2026-06-10T22:00:00+01:00` | No, `400 INVALID_REQUEST_BODY` |
| `30m`, `1.5h` | `start` only, and only without `end` |

Relative durations run that long after Amps receives the request. A window needs absolute times for both `start` and `end`.

## Times come back in UTC

Actions return `start` and `end` as UTC instants. A UK device in summer (BST, UTC+1):

```json theme={null}
{
  "id": "action_wd5ZqQtyBs",
  "state": "scheduled",
  "start": "2026-06-09T23:30:00.000Z",
  "end": "2026-06-10T03:30:00.000Z"
}
```

## Limits

| Rule | Error |
| - | - |
| `start` must be in the future. | `START_IN_PAST` |
| `start` must be within 30 days. | `START_OUT_OF_RANGE` |
| `start` must be a real date and time. | `START_INVALID_FORMAT` |
| `end` must be in the future, within 30 days, and after `start`. | `INVALID_TIME_WINDOW` |
| The device needs a known timezone for wall-clock times. | `TIMEZONE_UNRESOLVED`, `INVALID_TIMEZONE` |

All return `422`. `INVALID_TIME_WINDOW` carries `details.reason`. A relative `start` doesn't need the device's timezone.

## Daylight saving

| Case | Example (UK) | Behaviour |
| - | - | - |
| Time doesn't exist (clocks go forward) | `2026-03-29T01:30:00` | Rejected with `START_NONEXISTENT_WALL_CLOCK`. |
| Time happens twice (clocks go back) | `2026-10-25T01:30:00` | Ambiguous. Pick a time outside the repeated hour. |

`end` is compared with `start` in local time, so a window that crosses a clock change is valid as long as `end` is later on the wall clock.

## When a window ends

At `end`, Amps stops the command. EV chargers and thermostats are sent `idle`. Batteries have the window Amps wrote removed, so they return to whatever they run outside it. If another command has taken over the device before then, Amps leaves it alone. The action's `endedAt` records when the window actually closed.

To run something specific after the window, schedule it as a separate action. In sandbox, the device goes idle and holds where the window left it.

## Cancel a scheduled action

An action can be cancelled while it's still `scheduled`. See [Cancelling](/guides/push/cancelling).

Only one action can be active or scheduled per device. A new push that collides returns `409` unless you set `onConflict`. See [Conflicts](/guides/push/conflicts).

## Device schedules

To have a device run the program it already holds, such as a thermostat's own schedule, send the `auto.schedule` command.

<Callout icon="clock" color="#ED6D2C">
  **Coming soon.** Recurring schedules that Amps sets and runs on the device.
</Callout>

## Next steps

<CardGroup cols={2}>
  <Card title="Push" icon="arrow-up" href="/guides/push">
    The action body and lifecycle.
  </Card>

  <Card title="Conflicts" icon="code-merge" href="/guides/push/conflicts">
    Handle collisions with scheduled actions.
  </Card>

  <Card title="Webhooks" icon="bell" href="/guides/webhooks">
    Get notified when a scheduled action runs.
  </Card>

  <Card title="Battery cookbook" icon="battery-full" href="/cookbooks/battery">
    Charge in a cheap-rate window, and more.
  </Card>
</CardGroup>


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