> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nox.energy/llms.txt
> Use this file to discover all available pages before exploring further.

# Post Pv Control Schedule

> Submit steering schedules by providing a start and end time with a 1 min granularity of when you would like
pv production/grid export curtailment to be off or 0 % grid export curtailment.
 When you provide new scheduled controls for the same device
  that already had an existing control, then we will overwrite any commands scheduled for the pv
  with the newly provided schedules.
  If an active curtailment is already active(= off or 0 %) and your newly submitted schedule overlaps with the active one,
  then we will keep the active curtailment going until your end time has been reached or the start time has been reached and the
  control-type is different than the active one.
  `start_time` should be before `end_time` and `end_time` should be in the future. If not, the schedule will be rejected.
  You can provide a batch of different device_id's, each with custom or equal schedules.
  You can provide multiple schedules for the same device_id but keep in mind that the next time you
  update the schedule for that device_id, you will overwrite all the schedules for that device_id with the new ones you provide.
  There is a limit (250) to the number of updated device_id schedules you can provide in a batch.
  If you have many devices, you can split them into multiple batches.
  Make sure to not send schedules that are from users that have their external steering optimization disabled or are not yet compatible with our system.
  We will filter these devices out of them regardless. But it is best practice to only send us schedules for users that
  want to be curtailed and are compatible.
 

 Timestamp fields in UTC. 

 Time format examples: 
 * 2023-10-01T00:00:00Z
 
 * 2023-10-01T00:00:00 


 
 `control_type` can be set to `export_curtailment`, `production_curtailment` or `default`.
 
 * `export_curtailment` means that we will try to keep the grid export at 0 kW during the scheduled times by curtailing the pv production if needed.

 * `production_curtailment` means that we will try to keep the pv production at 0 kW during the scheduled times by curtailing the pv production if needed.

 * `default` means that we will not curtail the pv production or export and allow the grid export to be determined by the household consumption and pv production.
If the `end_time` of `default` control type is reached, it will keep it as default unless another schedule overwrites it.

 * It is possible to not provide an `end_time` for a schedule entry. We will handle this then as start command without reverting back to it's original state.
This is mostly recommended if you want the user to go to it's `default` state.
**NOTE**: 
 * The pv device might need some time to react. Please provide start times at
least 1 minute in the future to ensure the device can react in time. Some may react slower than others.



## OpenAPI

````yaml /api-docs/pv/openapi-pv.json post /v1/devices/pv/schedules
openapi: 3.1.0
info:
  title: NOX Energy API - PV
  description: >
    # PV API Documentation


    This documentation shows only the endpoints available to pv users.


    ## Authentication


    1. Get your API key from [NOX Energy](mailto:support@nox.energy).

    2. Include the API key in your API calls with the header: `x-api-key:
    YOUR_API_KEY`.


    ## Access Level


    This documentation is specifically for **pv users** who have access to these
    endpoints.


    Base URL: [https://api.nox.energy](https://api.nox.energy)
  version: 1.0.0
servers:
  - url: https://api.nox.energy
    description: Production Server
security:
  - ApiKeyAuth: []
tags:
  - name: Asset Info
    description: API to get basic information about your assets.
  - name: User Management
    description: API endpoints to manage users and their data.
paths:
  /v1/devices/pv/schedules:
    post:
      tags:
        - PV Control
      summary: Post Pv Control Schedule
      description: >-
        Submit steering schedules by providing a start and end time with a 1 min
        granularity of when you would like

        pv production/grid export curtailment to be off or 0 % grid export
        curtailment.
         When you provide new scheduled controls for the same device
          that already had an existing control, then we will overwrite any commands scheduled for the pv
          with the newly provided schedules.
          If an active curtailment is already active(= off or 0 %) and your newly submitted schedule overlaps with the active one,
          then we will keep the active curtailment going until your end time has been reached or the start time has been reached and the
          control-type is different than the active one.
          `start_time` should be before `end_time` and `end_time` should be in the future. If not, the schedule will be rejected.
          You can provide a batch of different device_id's, each with custom or equal schedules.
          You can provide multiple schedules for the same device_id but keep in mind that the next time you
          update the schedule for that device_id, you will overwrite all the schedules for that device_id with the new ones you provide.
          There is a limit (250) to the number of updated device_id schedules you can provide in a batch.
          If you have many devices, you can split them into multiple batches.
          Make sure to not send schedules that are from users that have their external steering optimization disabled or are not yet compatible with our system.
          We will filter these devices out of them regardless. But it is best practice to only send us schedules for users that
          want to be curtailed and are compatible.
         

         Timestamp fields in UTC. 

         Time format examples: 
         * 2023-10-01T00:00:00Z
         
         * 2023-10-01T00:00:00 


         
         `control_type` can be set to `export_curtailment`, `production_curtailment` or `default`.
         
         * `export_curtailment` means that we will try to keep the grid export at 0 kW during the scheduled times by curtailing the pv production if needed.

         * `production_curtailment` means that we will try to keep the pv production at 0 kW during the scheduled times by curtailing the pv production if needed.

         * `default` means that we will not curtail the pv production or export and allow the grid export to be determined by the household consumption and pv production.
        If the `end_time` of `default` control type is reached, it will keep it
        as default unless another schedule overwrites it.

         * It is possible to not provide an `end_time` for a schedule entry. We will handle this then as start command without reverting back to it's original state.
        This is mostly recommended if you want the user to go to it's `default`
        state.

        **NOTE**: 
         * The pv device might need some time to react. Please provide start times at
        least 1 minute in the future to ensure the device can react in time.
        Some may react slower than others.
      operationId: post_pv_control_schedule_v1_devices_pv_schedules_post
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/DevicesPVScheduleRequest'
              title: Request Body
            examples:
              schedule_example:
                summary: Sample pv control schedule
                value:
                  - device_id: PV1
                    schedules:
                      - start_time: '2025-08-05T10:15:00Z'
                        end_time: '2025-08-05T10:20:00Z'
                        control_type: export_curtailment
                  - device_id: PV2
                    schedules:
                      - start_time: '2025-08-05T10:15:00Z'
                        end_time: '2025-08-05T10:20:00Z'
                        control_type: production_curtailment
                  - device_id: PV3
                    schedules:
                      - start_time: '2025-08-05T10:15:00Z'
                        control_type: default
                  - device_id: PV4
                    schedules:
                      - start_time: '2025-08-05T10:15:00Z'
                        end_time: '2025-08-05T10:20:00Z'
                        control_type: export_curtailment
                      - start_time: '2025-08-05T10:21:00Z'
                        end_time: '2025-08-05T10:25:00Z'
                        control_type: production_curtailment
      responses:
        '200':
          description: All schedules accepted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DevicesPVScheduleResponse'
              example:
                rejected: []
                meta:
                  energy_supplier: Energy Supplier A
                  accepted_count: 12
                  rejected_count: 0
        '207':
          description: Partial success — some device_ids were rejected
          content:
            application/json:
              example:
                rejected:
                  - device_id: PV3
                    reason: end_time must be later than the start of the next minute.
                    reason_code: 6
                meta:
                  energy_supplier: Energy Supplier A
                  accepted_count: 10
                  rejected_count: 2
        '400':
          description: Invalid request parameters
          content:
            application/json:
              example:
                detail: >-
                  None of the provided device_ids allow steering or are
                  compatible.
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    DevicesPVScheduleRequest:
      properties:
        device_id:
          type: string
          title: Device Id
          description: Device ID to update control commands for it.
        schedules:
          items:
            $ref: '#/components/schemas/PVScheduleEntry'
          type: array
          title: Schedules
          description: List of commands to schedule for the pv device.
      type: object
      required:
        - device_id
        - schedules
      title: DevicesPVScheduleRequest
    DevicesPVScheduleResponse:
      properties:
        rejected:
          $ref: '#/components/schemas/DevicesPVScheduleRejectedListResponse'
          description: List of device IDs for which the schedule could not be applied.
        meta:
          $ref: '#/components/schemas/DevicesPVSchedulenMeta'
      type: object
      required:
        - meta
      title: DevicesPVScheduleResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    PVScheduleEntry:
      properties:
        start_time:
          type: string
          title: Start Time
          description: The start time for the schedule entry in ISO 8601 format.
        end_time:
          anyOf:
            - type: string
            - type: 'null'
          title: End Time
          description: >-
            The end time for the schedule entry. If not provided, only a start
            commandwill be scheduled. If provided, both start and end commands
            will be scheduled.
        control_type:
          $ref: '#/components/schemas/PVControlType'
          description: >-
            The control type for the schedule entry, determining the type of
            curtailment toapply. Possible values are 'export_curtailment',
            'production_curtailment', and 'default'.
      type: object
      required:
        - start_time
        - control_type
      title: PVScheduleEntry
    DevicesPVScheduleRejectedListResponse:
      properties:
        device_id:
          type: string
          title: Device Id
          description: Device ID for which the schedule could not be applied.
        reason:
          type: string
          title: Reason
          description: Reason why the schedule for the device was rejected.
        reason_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Reason Code
          description: >-
            Reason code mapping to why. {'A maximum of 250 device entries can be
            provided.': 1, 'A maximum of 25 schedule entries can be provided per
            device.': 2, 'Invalid device_id format. Device_id contains forbidden
            characters.': 3, 'Invalid date format in schedule entry. Please use
            ISO 8601 format (YYYY-MM-DDTHH:MM:SS) in UTC timezone. Example:
            2025-04-29T07:50:00': 4, 'start_time must be before end_time in
            schedule entry.': 5, 'end_time must be later than the start of the
            next minute.': 6, 'No properties found for the device. Could be due
            to recently connected device (less then 24 hours). Or this device
            does not exist.': 7, 'Error while fetching device properties for
            validation. Please try again later or contact support.': 8, 'You do
            not have permission to control this device.': 9, 'The user settings
            prevent it from being controlled.': 10, 'The device is currently not
            steerable, please check its steerable status.': 11}.
      type: object
      required:
        - device_id
        - reason
        - reason_code
      title: DevicesPVScheduleRejectedListResponse
    DevicesPVSchedulenMeta:
      properties:
        energy_supplier:
          type: string
          title: Energy Supplier
        accepted_count:
          type: integer
          title: Accepted Count
          description: Number of devices that had schedules successfully applied.
        rejected_count:
          type: integer
          title: Rejected Count
          description: Number of device schedules that were rejected.
      type: object
      required:
        - energy_supplier
        - accepted_count
        - rejected_count
      title: DevicesPVSchedulenMeta
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    PVControlType:
      type: string
      enum:
        - export_curtailment
        - production_curtailment
        - default
      title: PVControlType
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: 'API Key authentication. Enter your API key in the format: YOUR_API_KEY'

````