# Controlling devices ## Actions **Actions** are an asynchronous API pattern that represent a request for a device to perform an action, such as requesting a vehicle to start charging or changing the mode on an HVAC. You create actions by calling the appropriate endpoint, such as [Control Charging](https://developers.enode.com/api/reference#postVehiclesVehicleidCharging): ```bash curl {API_URL}/vehicles/{vehicleId}/charging \ -X POST \ -H "Authorization: Bearer {YOUR_ACCESS_TOKEN}" \ -d '{"action": "START"}' ``` For the latest supported actions across all devices, see our [API reference](https://developers.enode.com/api/reference#introduction). ### Vendor action states When you create an action in the API, Enode will attempt to execute that action on the device until it succeeds, fails (times out), or is cancelled. All vendor actions sent through Enode will at all times be in one of the following states. | State | Description | | | | --- | --- | --- | --- | | `PENDING` | The initial state. Enode is actively sending commands and monitoring the asset for changes. | | | | `CONFIRMED` | Successful state. We have verified via device data that the action was accepted and performed by the device. | | | | `FAILED` | Enode’s attempts to perform and validate the action on the device were unsuccessful and we have timed out. Actions transition to this state after a number of unsuccessful attempts and Enode becomes confident that subsequent retries won't succeed. Once an action has `FAILED`, Enode will no longer attempt this action. The number of attempts we make and timeout window varies by vendor and device. | | | | `CANCELLED` | One of the following is true... | A "precondition" for the action was not met. Some actions have “preconditions,” such as a vehicle needing to be plugged in to a charger or being reachable via the cloud. | Another action targeted the same device, overriding this one. | The `state` parameter on all actions reflects the latest state. ```bash { "id": "1e289a23-cc8a-4989-b465-4f5a9acaff15", "state": "PENDING", "createdAt": "2023-07-25T16:54:42.939Z", "updatedAt": "2023-07-25T16:54:42.939Z", "completedAt": null, "targetId": "83d32591-9931-4f62-878c-0d3933ca98c4", "targetType": "vehicle", "kind": "START", "failureReason": null } ``` All actions begin in `PENDING` unless we know the action will fail due to an unmet precondition, for which the API request to create the action will return a `CANCELLED` state. Common scenarios include: - an action to begin charging a vehicle that’s already fully charged - sending an action to change state of a device when the device is already in that state e.g., - asking a vehicle to start charging when it is already charging - setting an HVAC’s mode to `SCHEDULED` when it is already in `SCHEDULED` Vehicle charging actions that end up in `CANCELLED` or `FAILED` may have an associated `failureReason` with an explanation for why the vehicle ended up in that state (e.g., `NO_RESPONSE` for when a device doesn’t respond). For a full list, see our docs for controlling charging for [vehicles](https://developers.enode.com/api/reference#getVehiclesAction) and [chargers](https://developers.enode.com/api/reference#getChargersAction) . ### Listen to action updates We recommend listening to the `user:vendor-action:updated` webhook to understand when actions have transitioned states. Alternatively, you can periodically poll the `/{deviceType}/actions/{actionId}` endpoints for updates. Stay informed: Keeping accurate track of each action’s latest state is critical. Erroneously sending multiple actions to the same device will cancel subsequent actions and will lead to confusion and integration complexity. ## Levels of control Enode gives you flexibility to build automation and optimize energy usage how you want. You can always build advanced functionality on top of our basic actions, but Enode also offers Schedules and Smart Charging APIs that will manage additional complexity for you. | API | Description | Complexity | Recommendation | | | --- | --- | --- | --- | --- | | **Basic actions (e.g., [control charging](https://developers.enode.com/api/reference#postVehiclesVehicleidCharging))** | Send actions when and how you wish, leveraging your own data and algorithms for optimization | Low to high | - Users with simple use cases that exclude energy optimization | Large, sophisticated energy retailers who have the capacity to manage complex optimization schemes in-house | | [Scheduling](https://developers.enode.com/docs/scheduling) | Define rules for device behavior based on time of day and day of week, allowing for basic energy optimization or demand response solutions | Low | - Users who want a simple, intuitive strategy for energy optimization | Products with users in regions with static energy pricing | | [Smart charging](https://developers.enode.com/docs/smart-charging/introduction) | Our most sophisticated off-the-shelf optimization product that considers energy costs, charge deadlines, and minimum charge levels | Low | - Products with users in regions with dynamic energy pricing | | ## Best practices ### Interventions `capabilities` found on a device resource will let you know if there are any steps your users have to take before specific actions will work: ```bash { "id": "0637f895-1796-49d2-affb-16814f7efa10", "vendor": "VOLKSWAGEN", ... "capabilities": { "startCharging": { "interventionIds": ["87012776-355f-4d2c-b515-f53a78e3c582"], "isCapable": false }, ... } } ``` Review our guide on [Interventions](https://developers.enode.com/docs/integration-guide/user-device-lifecycle) to ensure you are handling known scenarios that may prevent actions from succeeding. ### Native device limitations Enode can control devices through a number of means, but we may have to deal with limitations found on devices or vendors themselves. The controls found on some devices may differ from the semantics of Enode’s API—for example, a vehicle may not have the native ability to arbitrarily “stop” charging but will have the ability to create charging schedules. In these cases, you should educate and reassure them about potential side effects such as schedules being created in the 1st party app. ### One action at a time Only one action from your integration should be active for a device at any given time. If Enode receives a new action for the same device before the previous one completes, the previous action transitions to the `CANCELLED` state. There is thus no benefit to sending a new identical command to override an existing command in a `PENDING` state. ### Interference by third parties Ask your users to make sure no other third parties are interfering with your application. As described in our [smart charging detailed guide](https://developers.enode.com/docs/smart-charging/onboarding#interference-by-third-parties) , apps controlled by charger, vehicle, or other apps can interfere with smart charging. Any other connected third parties can also make actions in your app confusing to interpret. You can listen for `user:{deviceType}:updated` [webhooks](https://developers.enode.com/docs/webhooks) to understand when actions may have taken place on a device that you did not control (e.g., if a vehicle stopped charging outside of your actions). ### Limit daily commands dispatched For maximum reliability, limit your application to sending _at most_ 6 commands per device, per day. Exceeding this can lead to connectivity errors that decrease action success rates and will result in a poor experience for your users.