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

# Set this HVAC device's schedule

> Set or replace the schedule on this HVAC device. The schedule's contents are device config, so they are written on the device itself rather than posted to a separate resource. The body is a non-empty `slots` array (each slot an `at` absolute-timestamp variant or a `time` wall-clock variant), an optional `recurrence` rule, and a schedule-level IANA `timezone` for `time`-variant slots. The route is published ahead of the scheduler; every call returns 501 until it lands.



## OpenAPI

````yaml /openapi.json put /hvac/{deviceId}/schedule
openapi: 3.1.0
info:
  title: Amps.ai API
  description: >-
    Energy device management API for batteries, EV chargers, solar inverters,
    and HVAC systems
  version: '1.0'
  contact: {}
servers:
  - url: https://api.amps.ai
    description: Amps API
security: []
tags: []
paths:
  /hvac/{deviceId}/schedule:
    put:
      tags:
        - HVAC
      summary: Set this HVAC device's schedule
      description: >-
        Set or replace the schedule on this HVAC device. The schedule's contents
        are device config, so they are written on the device itself rather than
        posted to a separate resource. The body is a non-empty `slots` array
        (each slot an `at` absolute-timestamp variant or a `time` wall-clock
        variant), an optional `recurrence` rule, and a schedule-level IANA
        `timezone` for `time`-variant slots. The route is published ahead of the
        scheduler; every call returns 501 until it lands.
      operationId: setHvacSchedule
      parameters:
        - name: deviceId
          required: true
          in: path
          description: The unique identifier for the HVAC device.
          schema:
            example: device_abc123
            type: string
      requestBody:
        required: true
        description: >-
          The schedule to set on the device: a non-empty `slots` array, an
          optional `recurrence`, and an optional `timezone` (required for
          `time`-variant slots). No `deviceId` in the body; the device is the
          URL.
        content:
          application/json:
            schema:
              type: string
            examples:
              dailyCharge:
                summary: Charge overnight every day (wall-clock slot)
                description: >-
                  A `time`-variant schedule that fires the same wall-clock
                  window every day in `Europe/London`. The slot carries a
                  `charge` command; once the scheduler ships, the platform
                  materialises one push per day on a rolling horizon.
                value:
                  timezone: Europe/London
                  recurrence:
                    rule: daily
                  slots:
                    - time: '00:30'
                      duration: PT5H
                      command: charge
                      parameters:
                        target:
                          value: 100
                          unit: percent
              weekdayOnly:
                summary: Charge weeknights only (recurrence by weekday)
                description: >-
                  Same overnight charge as `dailyCharge`, but the recurrence
                  rule restricts firing to ISO weekdays 1-5 (Monday-Friday).
                value:
                  timezone: Europe/London
                  recurrence:
                    rule: weekly
                    byweekday:
                      - 1
                      - 2
                      - 3
                      - 4
                      - 5
                  slots:
                    - time: '00:30'
                      duration: PT5H
                      command: charge
                      parameters:
                        target:
                          value: 100
                          unit: percent
              oneOffWindow:
                summary: A one-off windowed slot (absolute timestamp)
                description: >-
                  `at`-variant slot. No recurrence and no `timezone` field,
                  because the timestamp is absolute.
                value:
                  slots:
                    - at: '2026-06-08T22:00:00Z'
                      duration: PT7H
                      command: charge
                      parameters:
                        target:
                          value: 100
                          unit: percent
      responses:
        '200':
          description: Schedule set on the device.
          content:
            application/json:
              examples:
                schedule_set:
                  summary: Schedule set on the device
                  description: >-
                    The device now holds this schedule. The response echoes the
                    stored schedule, including a server-assigned `id` for the
                    generic `GET /schedules` list and a derived `nextFireAt`.
                  value:
                    id: sched_abc123
                    deviceId: device_abc123
                    deviceType: hvac
                    state: active
                    timezone: Europe/London
                    recurrence:
                      rule: daily
                    slots:
                      - time: '00:30'
                        duration: PT5H
                        command: charge
                        parameters:
                          target:
                            value: 100
                            unit: percent
                    updatedAt: '2026-06-01T12:00:00.000Z'
                    nextFireAt: '2026-06-02T00:30:00.000Z'
        '404':
          description: Device not found or access denied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                deviceNotFound:
                  summary: No device matches the ID for this customer
                  value:
                    success: false
                    error:
                      code: DEVICE_NOT_FOUND
                      message: No matching device was found for the supplied details.
                      details:
                        description: Device not found or access denied
                    meta:
                      requestId: req_5pH1cQbY
                      timestamp: '2026-04-29T12:00:00.000Z'
                      path: /hvac/device_unknown_999
                      latencyMs: 5
        '501':
          description: Scheduler not yet implemented.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                not_implemented:
                  summary: Scheduler is not yet wired up
                  value:
                    success: false
                    error:
                      code: NOT_IMPLEMENTED
                      message: This API operation is not implemented.
                      details:
                        description: Setting a device schedule is not yet implemented.
                    meta:
                      requestId: req_NotImplYet1
                      timestamp: '2026-04-29T12:00:00.000Z'
                      path: /hvac/device_abc123/schedule
                      latencyMs: 1
      security:
        - api-key: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl --request PUT \
              --url 'https://api.amps.ai/hvac/device_abc123/schedule' \
              --header 'x-api-key: amps_sk_test_xxxxxxxxxxxxxxxxxxxxxxxx' \
              --header 'content-type: application/json' \
              --data '{
                "timezone": "Europe/London",
                "recurrence": {
                  "rule": "daily"
                },
                "slots": [
                  {
                    "time": "00:30",
                    "duration": "PT5H",
                    "command": "charge",
                    "parameters": {
                      "target": {
                        "value": 100,
                        "unit": "percent"
                      }
                    }
                  }
                ]
              }'
        - lang: javascript
          label: Node
          source: >-
            const response = await
            fetch('https://api.amps.ai/hvac/device_abc123/schedule', {
              method: 'PUT',
              headers: {
                'x-api-key': 'amps_sk_test_xxxxxxxxxxxxxxxxxxxxxxxx',
                'content-type': 'application/json',
              },
              body: JSON.stringify({
                "timezone": "Europe/London",
                "recurrence": {
                  "rule": "daily"
                },
                "slots": [
                  {
                    "time": "00:30",
                    "duration": "PT5H",
                    "command": "charge",
                    "parameters": {
                      "target": {
                        "value": 100,
                        "unit": "percent"
                      }
                    }
                  }
                ]
              }),
            });


            const data = await response.json();
        - lang: python
          label: Python
          source: |-
            import requests

            url = 'https://api.amps.ai/hvac/device_abc123/schedule'
            headers = {
                'x-api-key': 'amps_sk_test_xxxxxxxxxxxxxxxxxxxxxxxx',
                'content-type': 'application/json',
            }
            payload = {
                "timezone": "Europe/London",
                "recurrence": {
                    "rule": "daily",
                },
                "slots": [
                    {
                        "time": "00:30",
                        "duration": "PT5H",
                        "command": "charge",
                        "parameters": {
                            "target": {
                                "value": 100,
                                "unit": "percent",
                            },
                        },
                    },
                ],
            }

            response = requests.put(url, headers=headers, json=payload)
            data = response.json()
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Always `false` for error responses.
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - INVALID_CREDENTIALS
                - INVALID_API_KEY
                - INVALID_MFA_CODE
                - MFA_REQUIRED
                - ACCOUNT_LOCKED
                - UNSUPPORTED_CREDENTIAL_TYPE
                - DEVICE_NOT_FOUND
                - DEVICE_OFFLINE
                - DEVICE_UNAUTHORIZED
                - NO_DEVICES_FOUND
                - COMMAND_FAILED
                - COMMAND_NOT_SUPPORTED
                - EXECUTION_NOT_SUPPORTED
                - MODE_OVERRIDDEN
                - VPP_LOCKED
                - INVALID_PARAMETERS
                - INVALID_OEM_PARAMETERS
                - INVALID_TIME_WINDOW
                - BIND_NOT_SUPPORTED
                - SCHEDULER_ACTIVE
                - SCHEDULER_FULL
                - UNSUPPORTED_AUTH_PATH
                - NETWORK_ERROR
                - RATE_LIMITED
                - SERVICE_UNAVAILABLE
                - TIMEOUT
                - NOT_YET_AVAILABLE
                - SIMULATED_FAILURE
                - UNKNOWN_ERROR
                - CREDENTIAL_NOT_FOUND
                - OEM_CIRCUIT_OPEN
                - COMMAND_NOT_APPLIED
                - STALE_ACTION
                - DEFERRED_SCHEDULE_FAILED
                - UNROUTABLE_ACTION_TYPE
                - UNAUTHORIZED
                - EXPIRED_TOKEN
                - FORBIDDEN
                - INSUFFICIENT_PERMISSIONS
                - LIVE_ACCESS_DISABLED
                - VALIDATION_ERROR
                - INVALID_INPUT
                - INVALID_REQUEST_BODY
                - EMPTY_SETTINGS
                - PAYLOAD_TOO_LARGE
                - UNSUPPORTED_MEDIA_TYPE
                - NOT_FOUND
                - METHOD_NOT_ALLOWED
                - CONFLICT
                - CONFLICT_IN_EXECUTION
                - GONE
                - RATE_LIMIT_EXCEEDED
                - INTERNAL_ERROR
                - NOT_IMPLEMENTED
                - BAD_GATEWAY
                - GATEWAY_TIMEOUT
                - DEVICE_TYPE_MISMATCH
                - CONSENT_REVOKED
                - DEVICE_OVERAGE
                - SETTINGS_STORE_UNAVAILABLE
                - ACTION_NOT_FOUND
                - DIRECT_ACTION_UNSUPPORTED
                - UNSUPPORTED_ACTION
                - UNSUPPORTED_MODE
                - UNSUPPORTED_PARAMETER
                - UNSUPPORTED_UNIT
                - PARAMETER_OUT_OF_RANGE
                - START_IN_PAST
                - START_OUT_OF_RANGE
                - START_OFFSET_NOT_ACCEPTED
                - START_INVALID_FORMAT
                - START_NONEXISTENT_WALL_CLOCK
                - TIMEZONE_UNRESOLVED
                - INVALID_TIMEZONE
                - ACTION_NOT_CANCELLABLE
                - STRATEGY_NOT_SUPPORTED
                - UNSUPPORTED_SETTING
                - READ_ONLY_SETTING
                - INVALID_SETTING_UNIT
                - INVALID_SETTING_VALUE
                - SETTING_OUT_OF_RANGE
                - NO_OP
                - NO_OVERRIDE
                - AVAILABILITY_ENV_UNSUPPORTED
                - UNSUPPORTED_COMBINATION
              description: >-
                Machine-readable error code (e.g. `VALIDATION_ERROR`,
                `CONFLICT`, `UNSUPPORTED_MODE`). Stable across releases; safe to
                switch on.
            message:
              type: string
              description: Human-readable error message.
            details:
              description: >-
                Structured context for the error: which fields were invalid,
                which actions conflicted, which capabilities the device
                declares. Shape varies by error code.
              type: object
              properties: {}
              additionalProperties: {}
          required:
            - code
            - message
          description: Error envelope.
        meta:
          type: object
          properties:
            requestId:
              description: >-
                Unique request identifier. Echoes the `x-request-id` header when
                present; otherwise generated server-side.
              type: string
            timestamp:
              type: string
              description: ISO 8601 timestamp when the error response was built.
            path:
              type: string
              description: Request path that produced the error.
            latencyMs:
              type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
              description: Server-side processing time in milliseconds.
          required:
            - timestamp
            - path
            - latencyMs
          description: Request metadata.
      required:
        - success
        - error
        - meta
      title: Error Response
      description: >-
        Uniform error response. The `error.code` identifies the failure,
        `error.message` carries a human-readable explanation, and
        `error.details` carries structured context (failed fields, conflicting
        action IDs, supported capabilities) where relevant.
  securitySchemes:
    api-key:
      type: apiKey
      in: header
      name: x-api-key

````