Calling internal GET /api/chargers/[id]/settings
Hello, Zaptec devs are here!
We’ve noticed that your integration is making sequential calls to the following endpoints:
GET api/chargers/[id]/state
GET api/chargers/[id]/settings
Just a quick note: the state endpoint already includes all the data returned by the settings endpoint — in fact, settings is simply a subset of state. While you might occasionally see slight differences in overlapping fields, this typically happens when a charger hasn’t updated its values yet. Once it does, the accurate value will be reflected in state.
Additionally, please note that the settings endpoint is considered internal. It is subject to change or rate limiting without prior notice, and we recommend avoiding reliance on it for production use.
We kindly ask that you remove the settings call (https://github.com/custom-components/zaptec/blob/master/custom_components/zaptec/api.py#L604-L613) if you're already using state, because we have plans to forbid usage of this endpoint by external parties.
We truly appreciate your support in optimizing the integration. If you have any questions or need help making this adjustment, feel free to reach out.
Thanks again for your cooperation!
The reason settings were added is because it had datapoints that state didn't. But I see know from my own installation that settings doesn't contain any additional information. I'll update the code according to the request.
Would it be possible to offer two requests:
-
The reason for (frequent) polling of these endpoints regularly from this integration is that there are many data attributes that change that isn't transmitted in the service bus subscription. If more information were regularly updated through the service bus, then the need for doing frequent endpoint calls would be reduced. Most information in the endpoints are static, but the user expect updates for the data points that change.
-
In full disclosure, please be advised that the integration is also making a couple of undocumented API calls that have been reverse engineered from the Zaptec Portal webapp. They are labelled in
api.pywith "Undocumented API call". E.g. authorize charge, setting permanent cable lock, setting authentication required. These are popular features the users are using and want to have control over. I'd like to request that these operations are made available in the official API.
The reason settings were added is because it had datapoints that state didn't. But I see know from my own installation that settings doesn't contain any additional information. I'll update the code according to the request.
That would be really nice, thank you. Can you give an example of missing states?
And regarding your points:
- What are the missing states you are referring to? The current list of states sent to the service bus was intended to sufficiently support ongoing charging sessions. Any other less frequently changing states can typically be retrieved from the state endpoint. Also worth noting: our plan is to eventually deprecate the per-installation service bus (see API reference), though we're working on a replacement for that (no timelines yet).
- Yes, we noticed that :) , but this one was most critical. The other place we noticed that needs improvement is sending of
Pause/Resumecharging, no matter of state charger is in (for example,Disconnectedstate). In general,Pauseshould be sent only if charger isCharging, andResumeonly if charging isPaused. But we will come back to you with more details once we revisit other places.
The other place we noticed that needs improvement is sending of
Pause/Resumecharging, no matter of state charger is in (for example,Disconnectedstate). In general,Pauseshould be sent only if charger isCharging, andResumeonly if charging isPaused. But we will come back to you with more details once we revisit other places.
It would be nice if you could add the issues for findings like this. Home Assistant is rather stateless, so this will require some system thinking into the overall architecture. It would be nice to get all those inputs before going into a bigger rewrite.
Just a quick note: the
stateendpoint already includes all the data returned by thesettingsendpoint — in fact,settingsis simply a subset ofstate. While you might occasionally see slight differences in overlapping fields, this typically happens when a charger hasn’t updated its values yet. Once it does, the accurate value will be reflected in state.
I tested this on my system at home and I found three fields that are not present anywhere other than in settings.
["CurrentInMaximum", "DefaultOfflineCurrent", "CurrentInMinimum", "DefaultOfflinePhase"]
This shows are information in settings which is not reflected in the charger info and state endpoint. The use case for CurrentInMinimum and CurrentInMaxiumum is to be able to configure the current range on the charger. In order to have a control for them, the current value must be read, and the settings endpoint provides that.
Please advise for other endpoints that can provide this information and functionality. I'm happy to change the code.
The other place we noticed that needs improvement is sending of
Pause/Resumecharging, no matter of state charger is in (for example,Disconnectedstate). In general,Pauseshould be sent only if charger isCharging, andResumeonly if charging isPaused. But we will come back to you with more details once we revisit other places.
Can you please provide documentation for this, so we can refer to this when changing the behavior.
CurrentInMaximum same as state 510 - ChargeMaxCurrent
CurrentInMinimum same as state 511 - ChargeMinCurrent
DefaultOfflinePhase same as state 522 - ChargerOfflinePhase
DefaultOfflineCurrent same as state 523 - ChargeOfflineCurrent
Settings are only subset of states, matching by id (settingId-stateId), you can freely ignore the labels
I will get back to you for Pause/Resume charging.
PS! @ivastokic Do you have a good way to raise developer questions to Zaptec? I've only tried 1. line support and it takes so much explaining and efforts to get to the core question, which takes too much time. As a maintainer for the Zaptec integration, I sometimes have technical questions I'd like to discuss. Since there are many users of this integration, it's in our joint interest to get this working right.
Have Zaptec any plans for graphql? There are many attributes downloaded from the various end-points that are not used by this HA integration, but they are part of the data set. It would be a great resource reduction to only query the fields (and hierarchy) that are needed.
@sveinse I forwarded your question to our integrations engineer, who will take over this matter.
As of GraphQL support — no, no plans or considerations towards it. We are, however, actively working on the next generation API and will put in our list reducing the response size.
@sveinse Regarding Pause/Resume, you can find here more details.
In order to avoid command failing (error code 528 - DeviceCommandRejected), just use current states of the charger on decision whether command should be sent or not.
CurrentInMaximum same as state 510 - ChargeMaxCurrent CurrentInMinimum same as state 511 - ChargeMinCurrent DefaultOfflinePhase same as state 522 - ChargerOfflinePhase DefaultOfflineCurrent same as state 523 - ChargeOfflineCurrent
Settings are only subset of states, matching by id (settingId-stateId), you can freely ignore the label
Back to our initial request, are you able to remove GET /api/chargers/[id]/settings? By using settings, it is possible to set some of the properties on the charger, but then charger reports them all back in states. So, in that way, states should be sufficient for all your needs.
PS! @ivastokic Do you have a good way to raise developer questions to Zaptec? I've only tried 1. line support and it takes so much explaining and efforts to get to the core question, which takes too much time. As a maintainer for the Zaptec integration, I sometimes have technical questions I'd like to discuss. Since there are many users of this integration, it's in our joint interest to get this working right.
Have Zaptec any plans for graphql? There are many attributes downloaded from the various end-points that are not used by this HA integration, but they are part of the data set. It would be a great resource reduction to only query the fields (and hierarchy) that are needed.
@sveinse related to your first question. Thanks for raising this I completely understand how time-consuming it can be to explain technical issues through first-line support. We’ve recently made improvements to the way integration-related requests are escalated, introducing a more structured support flow with defined levels of technical assistance. These updates have been finalized and communicated internally, so you should see an improvement in response times and issue resolution. That said, if you’re still encountering delays or feel the current process isn’t working well for your needs, please don’t hesitate to let us know. we’d be happy to look into alternative ways to support you more effectively.
Hello @sveinse We’ve noticed that your integration is still making sequential calls to the internal endpoint GET api/chargers/[id]/settings. As mentioned earlier, this endpoint isn’t intended for external use and falls outside our API fair use policy.
Could you please take a look and let us know your plans or an estimated timeline for updating the integration? We're happy to assist if you need any support during the transition.
Thanks in advance, and looking forward to your update!
@bonfaceOchieng this has been understood and acknowledged earlier. However, the work in this integration is based on voluntary efforts only, and there is no central governance of the integration other than a couple of maintainers (such as me). We are dependent on contributions in the form of PRs or the time and opportunity to make the changes. As such there is no concrete plans for making this migration unfortunately.
I am thankful for the offer of support!
Hello @sveinse Thanks for your response, and we truly appreciate the effort you and the other maintainers put into supporting this integration especially on a voluntary basis.
We understand the limitations around time and governance in such setups. That said, since continued use of the internal GET api/chargers/[id]/settings endpoint falls outside our fair use policy, we kindly ask that a plan for phasing it out be considered, even if it’s on a best-effort basis.
@bonfaceOchieng The plan is to phase out these, but when is what's uncertain.
Since there is no formal organization driving this integration, I cannot talk for other than myself. Unfortunately, I'm not in a position where I'm able to start working on this right now. This is the way community driven software projects works, unfortunately. This project is not above critical mass which drives and organizes itself. I think the best thing we can do is to do a call-out for contributions, perhaps on the front README. This not out of unwillingness. We'll do our best, but I don't know about a plan unless an individual is able to commit. -- We are grateful for all contributions and I'd strongly encourage Zaptec to contribute.
The (new?) fair use policy restricts the usage of reverse engineered endpoints. We have some features which has been made available by reverse engineering. This is because the official Zaptec API doesn't offer the mechanism and users have been requesting that functionality. If we need to remove these features, it will reduce the usability of the integration. Can we make requests to Zaptec for adding missing functions to the public API?
PS! Front page updated: https://github.com/custom-components/zaptec/blob/master/README.md
Hello @sveinse Thank you for your feedback , it's much appreciated.
Could you please clarify which specific features you're referring to that have been accessed through reverse engineering and are not exposed via the official Zaptec API? It would be helpful if you could share the endpoints you're using and how you're utilizing them.
Also, we’d like to inform you about some upcoming changes to endpoints related to account and password management. You can find the details here: https://docs.zaptec.com/page/upcoming-authentication-provider-migration#/
If you're currently using any of the affected endpoints, please ensure to make the necessary adjustments when the changes take effect around September.
@bonfaceOchieng The best way is to navigate to https://github.com/custom-components/zaptec/blob/master/custom_components/zaptec/api.py and search for "Undocumented API call"
@bonfaceOchieng do you have a simulator of a Zaptec charger and installation? Developing this integration as a consumer with only access to my own personal charger is tedious and slow. E.g. I can only test a charge cycle at the speed that the car permits. Doing too many starts and stops with the car is not healthy for the car battery, which limits the testing speed of the corner cases.
Hello @sveinse, I will check internally and get back to you on this.
@sveinse Could you please clarify the specific behavior you'd like to emulate or test? This will help us determine whether we can offer a suitable solution or provide relevant advice. At the moment, we do not have a publicly available simulator.
@bonfaceOchieng
We have implemented a fix for the use of /api/chargers/{id}/settings in PR #183 as described in this issue. However, we observe some challenges regarding getting reliable updates of the values.
The reason for using extensive polling and short intervals is because the Zaptec cloud can be slow to update the parameters on changes. The users expect near-realtime update of the Zaptec parameters in HA, where the data might be used for other triggers and automations. Service bus should fix that, but as can be shown, not all data updates are reliably updated this way, so polls are still needed.
Polls will often return old values if they occur too close to the command. Issue #189 highlights the effects of this behavior. In the current design it leads to ambulating values of NEW -> OLD -> NEW with minutes between. It is evident that we need a more advanced solution than just updating to the last received value, such as looking at timestamps. I wish that we didn't need to have this complicated logic thou.
When sending commands to Zaptec cloud, how can we reliably know when all parameters from this command have been updated?
Let's assume the integration reduce scheduled polling to a minimum with an order of once per hour. The issue #189 shows that the service bus is not always updating all its data when a command is sent, and that immediate polling might return old data. The way I see it, this system design requires rather frequent sequence of polling after a command is issued to ensure the dataset is up to date.
Questions
This can help us make a more robust solution:
- Does every user have access to the service bus? Will we have any users that must rely on polling alone?
- How long time is required from sending a command to the Zaptec cloud until polling returns the correct updated value?
Bug?
I notice that sending setting of ChargerMaxCurrent doesn't always result in the service bus event ChargerMaxCurrent. Correspondingly setting ChargerMinCurrent doesn't always result in ChargerMinCurrent from the service bus. But what it does seem is that when setting ChargerMaxCurrent I always get a ChargerMinCurrent event. And Settting ChargerMinCurrent seems to always send a ChargerMaxCurrent event. Speculation: Is there a mixup of these two parameters in the Zaptec cloud handling since it seems to send the opposite value and not always the one that have changed?
We have implemented a fix for the use of /api/chargers/{id}/settings
Thank you for this one, is it already deployed on your side, or it depends on users when they upgrade version? Because it is still pretty much the same amount of GET state and settings requests.
Regarding other questions, let me go quick with how update works
- Update request for
MaxCurrentis sent; it updates charger's DeviceTwin on IoT hub - Once charger picks up this value, and report it back, it will end up in states (state with
Id-510will updated)
How to find out that charger accepted new value:
- By pooling charger states, until you have your new value updated -> it means that charger has now newest value. There is no caching like mentioned here, this is outdated info (fixed now). So, if value in states in still old one it only means that charger hasn't reported it back yet.
- Installation message subscription - even it is still active and convenient for getting updates, it is deprecated, so I would not advice to go with that approach. It is in planning phase to be decided if something will replace it for small integrators.
Edge case:
- Once update request is sent and DeviceTwin is updated,
MaxCurrentvalue is not reported back by charger - you can try again with updating (recommended to wait ~1min) with slightly different value (few decimals up or down, it is only important that value is not the same, then update will be ignored)
Bug (MaxCurrent not reported to serviceBus):
- Cause for value not been published to serviceBus is only edge case from above. I checked timespan when you were testing, and all your updates are in place. Good to mention that you have Tibber on your installation, that controls charging also via
MaxCurrent, so that could bring some confusion which value wins, and why it's there now (is it coming from HomeAssistant integration or Tibber's one). - There is no mixup with those 2 parameters
General recommendations:
- Update MaxCurrent value only during active charging
- Avoid frequent updates, neither car or charger likes them; adjusting the current value once every few mins is ok, but very frequent start/stop charging should be avoided
- Once MaxCurrent is updated (ideally it takes not more that few seconds), wait ~1min for charger to report back value; if it doesn't happen, try again with adjusting explained in 'Edge case'
If you have any more questions, just let us know.
@ivastokic Thank you for the response
Release
We need a release to push this to users, and I don't plan to until we've closed most issues related to the API policy fixed #188 and tracked here https://github.com/custom-components/zaptec/milestone/1. I don't think we have scoped all work yet and I expect the number of issues to rise, as the API policy is requiring us to change the setup quite a bit.
Service bus
The API hints at not doing too frequent polls. It mentions once per hour. It's sad if the service bus is deprecated and going away, because a push mechanism significantly reduces the need for polling.
HA users expect near-realtime update of the data. In fact HA doesn't like it when data is arriving late. #180 , #178 and #162 are examples of that if it's of interest. Anything slower than a minute would start to be problematic for graphing and regulation in HA.
Yet here we are discussing to reduce the poll interval. Please advice on what we can do to get as near-realtime update of the parameters as possible in HA, without creating too great load on your API endpoints.
Update algorithm
From the integration perspective there are three types of independent events:
- Scheduled poll update. Today its defaulting to 60 seconds.
- Commands issued by integration (start, stop charge, parameter change)
- Zaptec data push via service bus
If (3) was reliable for data updates, we could reduce (1) to significantly longer intervals. Maybe as much as 1 hour. But since (3) is deprecated, we will still require a low as possible value for (1).
As for (2) the following sequence will be considered:
- Send the command to Zaptec
- Wait 1-5 seconds and poll for updates. This is important to get UX feedback in HA.
- Wait Y time, poll again for updates. Here Y can be 20-60 seconds. The intentions is to catch any other parameters that might be updating slowly on the Zaptec server side.
AOB
PS! In my personal setup I don't really want Tibber to control anything. How can I remove them completely? I'm controlling the charging completely from HA. EDIT: I've reached out to Tibber support. It seems you need to contact their customer support for them to remove the integration of the Zaptec charger. Thanks for the tip.
PPS! My colleague at work (Espen Wathne) sends his regards. I'm a manager working closely with him.
I don't think we have scoped all work yet and I expect the number of issues to rise
Given this, along with other unplanned tasks, would it be possible to roll out the changes you’ve already completed? As we discussed earlier, this is a critical endpoint that's called quite frequently. It’s also great that you've switched to using POST api/chargers/[id]/update instead of POST api/chargers/[id]/settings to update the settings — we really appreciate that. If possible, it would be helpful if you could publish just those changes first.
Regarding the polling mechanisms, it might be useful to separate them into two modes:
- Active Charging Session – When the charger is connected and charging is ongoing.
- Disconnected / Idle State – When the charger is not in use (e.g.,
ChargeOperationMode710 = 1).
For the disconnected state, frequent data fetching isn’t necessary since the charger status remains mostly unchanged. During an active session, polling can be more frequent.
As for points of interest:
There are charger states 553 (TotalChargePowerSession, reported pretty often), and state 554 (SignedMeterValue, for 3rd parties, hourly for Go chargers). Based on the timestamps, you can gauge how often to fetch charger states. Once per minute — or every few minutes — should be sufficient.
Regarding MaxCurrent updates:
Who determines the value of MaxCurrent? Is it based on house consumption or another factor? It’s also good to do updates only during active sessions. To reflect the new value in the charger state, good to do something as you mentioned — wait a few seconds after the update, then fetch the states to verify the change. If there’s no update, you might wait up to a minute, check again, and if the value is still unchanged, retry the update (perhaps using a slightly different value, since identical ones are ignored).
These are general recommendations — it’s possible some of this is already implemented on your side.
PS: I can see that you still have Tibber on your installation. You can remove it from Portal, but I guess there is a way via their app? You probably have some subscription for their services. PPS: Nice to work with Espen, sending back regards! :)
I don't think we have scoped all work yet and I expect the number of issues to rise
Given this, along with other unplanned tasks, would it be possible to roll out the changes you’ve already completed? As we discussed earlier, this is a critical endpoint that's called quite frequently. It’s also great that you've switched to using
POST api/chargers/[id]/updateinstead ofPOST api/chargers/[id]/settingsto update the settings — we really appreciate that. If possible, it would be helpful if you could publish just those changes first.
I understand the desire for getting this fixed -- as do we. We're working as fast as we are able to with this, but I need to ask for some patience, please. It's not just Zaptec's guidelines that has to be accounted for, but also those of Home Assistant. We don't have an API test suite for the Zaptec API, no simulator, and no automated testing. We only have our own actual personal chargers (and cars) to test on and it takes time (since I don't want to destroy the car by changing too frequent).
Please be advised the nature of Home Assistant: Its a suite that users run locally on their own system. When we (the Zaptec integration) push a new release, it will be up to the users to chose when to download the update. We don't control it and we can't push it. It must be expected that it will take time until this new version is fully deployed among the userbase. This is also why we need to be certain the release is good before we deploy.
We haven't implemented the fix for the staggered polls yet. We are still regularly polling installation/{id} and charger/{id} at frequent intervals. I'd like to assume that you're interested it getting this fixed too.
Regarding the polling mechanisms, it might be useful to separate them into two modes:
- Active Charging Session – When the charger is connected and charging is ongoing.
- Disconnected / Idle State – When the charger is not in use (e.g.,
ChargeOperationMode710 = 1).For the disconnected state, frequent data fetching isn’t necessary since the charger status remains mostly unchanged. During an active session, polling can be more frequent.
Thanks. From what I have gathered I'm planning the following scheme wrt. polling:
| State | Endpoints | Poll interval |
|---|---|---|
| Active charging | chargers/{id}/state |
60 second (1) |
| Disconnected/idle | chargers/{id}/state |
10 minute |
| Info updates | installation/{id}, charger/{id}, chargerFirmware/installation/{id} |
60 minute (2) |
| Structure | installation, installation/{id}/hierarchy |
?? (3) |
| Commands | chargers/{id}/state |
1, 5 and 15 seconds (4) |
- (1) Device state dependent poll interval is new logic for us. This is our biggest uncertainty and timeline risk. Today there is only one poll interval (60 seconds) where both state and infos are updated regularly.
- (2) I'm planning to evaluate if there are any data changing here at all. If there is not, then this rate can be reduced
- (3) I'm not certain how often this is really needed, or at all. Adding or removing chargers is an extremely rare event for the HA users
- (4) This is commands issued by the HA UX. The sequential polls are to ensure the HA UI is updated as soon as possible, yet accounting for processing time in the Zaptec cloud. If this system works good, it can allow for even longer general poll intervals. The exact delays can be fine tunes later.
@ivastokic How does this look like from your perspective? If this rates works for you and the users, this will be several orders of magnitude less requests to the Zaptec end-points. Today its around ~360 requests/hour, reducing it by x40 during idle and x5.7 during charging.
PS! I am aware of the hard rate-limit at 10 request per second to prevent stampeding bulls. Are there any other rate limits for longer period of time e.g. X number of request per hour or day?
Are there any other rate limits for longer period of time e.g. X number of request per hour or day?
No other limits than 10req/s per user, no matter of endpoint.
@ivastokic How does this look like from your perspective?
Sounds much better. But, most important here is to move from non-public endpoints. If listed ones are all you use, then it is fine. Few comments on bullet-points:
Disconnected/idle - during this period you can receive charger's info like Temperature, Humidity, SignalStrength, IsOnline (could be changed if charger went offline), some Diagnostics. So, interval depends if you are showing those somewhere.
(1) Device state dependent poll interval is new logic for us. This is our biggest uncertainty and timeline risk. Today there is only one poll interval (60 seconds) where both state and infos are updated regularly.
I dont think you should be concerned here, your plan to do poll some endpoint less that others is fine, if data that you receive are more or less static, why polling so often.
When it comes to GET chargers/{id}/state you will use same interval as before during charging, so there shouldn't be any difference.
For updates POST api/chargers/[id]/update, the best approach is to send an update when there is actual change in value, not based on polling interval. Sending same value wont result in any change.
(2) I'm planning to evaluate if there are any data changing here at all. If there is not, then this rate can be reduced
At least chargerFirmware/installation/{id} could be once a day, I guess you are using this to present somewhere that there is new firmware version?
For installation/{id}, charger/{id}, depends which fields from those entities you are using, then we can see how to adjust pooling interval.
(3) I'm not certain how often this is really needed, or at all. Adding or removing chargers is an extremely rare event for the HA users
Yes, I guess most of them are one charger installations. But, once charger is added to an installation, does that affect on MaxCurrent that you are sending in any way (evenly shared current between chargers, or so)? Again, depends which fields from those entities you are using, then we can see how to adjust pooling interval. For this rare actions, you can always go with clicking button somewhere in UI - saying 'Do sync' and then it goes and fetch all listed endpoints at once.
(4) This is commands issued by the HA UX. The sequential polls are to ensure the HA UI is updated as soon as possible, yet accounting for processing time in the Zaptec cloud. If this system works good, it can allow for even longer general poll intervals. The exact delays can be fine tunes later.
You listed here in Endpoints only chargers/{id}/state, but I guess POST api/chargers/[id]/update and POST api/chargers/[id]/sendCommand are involved, so checking state is result of those actions? But, in general, it could work, I would go with 2-3 instead of 1, then 7, 15, 60, then you retry update if no changes in states.
I'm really curious how this part works, based on which inputs HA users adjust MaxCurrent or sending commands.
Sounds much better. But, most important here is to move from non-public endpoints. If listed ones are all you use, then it is fine.
With reference to https://github.com/custom-components/zaptec/issues/188#issuecomment-3041337515, we are still using these undocumented endpoints:
POST chargers/{id}/authorizechargePOST chargers/{id}/localSettings(for setting cable lock and HMI brightness)
Especially authorize charge and setting cable lock is highly sought after features which is lacking from the public API. I have no immediate plans on removing them just yet and I'd like to discuss these with you later. Now we're focusing on the system for polling.
Disconnected/idle - during this period you can receive charger's info like Temperature, Humidity, SignalStrength, IsOnline (could be changed if charger went offline), some Diagnostics. So, interval depends if you are showing those somewhere.
HA is revolved around entities. Each entity is one parameters/attribute that the charger endpoint provides. We subscribe to a lot of the data points that Zaptec provides. This list of parameters used to be smaller, but it has grown after user request. Each of these may be used by the user to trigger further automation, gather statistics and so on.
I don't know if you have seen the Zaptec integration in HA, but here is a motif of the entities displayed for a charger:
I dont think you should be concerned here, your plan to do poll some endpoint less that others is fine, if data that you receive are more or less static, why polling so often. When it comes to
GET chargers/{id}/stateyou will use same interval as before during charging, so there shouldn't be any difference.
OK. Then I think we skip the device- and state dependent and polling of GET chargers/{id}/state for now. Then every charger will be polled every 60 seconds.
This is good as it's most common for HA integration to only have one account-wide poll interval, so making this device and state specific, would be more work which delay the release.
For updates
POST api/chargers/[id]/update, the best approach is to send an update when there is actual change in value, not based on polling interval. Sending same value wont result in any change.
No no. We never POST more than once (as per web practices on POST and PUT). The only time it might happen is if the user press a button that results in a POST and the resulting UI updates too slow for the user and the user press the button again. This is why I'm stressing the need for being more aggressive in polling state after a POST.
You listed here in Endpoints only
chargers/{id}/state, but I guessPOST api/chargers/[id]/updateandPOST api/chargers/[id]/sendCommandare involved, so checking state is result of those actions?
Yes. With "command" I mean any action initiated by the user by HA. It involves sending to POST installation/{id}/update, POST chargers/{id}/update, POST charger/{id}/SendCommand/{cmd} and the two undocumented ones listed further up.
But, in general, it could work, I would go with 2-3 instead of 1, then 7, 15, 60, then you retry update if no changes in states. I'm really curious how this part works, based on which inputs HA users adjust MaxCurrent or sending commands.
Got it. Then I'll set it up with 2, 7, 15. There is no need to go to 60, because it will be picked up by the timed poll interval at 60 seconds anyways.
ChargerMaxCurrent or InstallationAvailableCurrent are frequently used by users to regulate the amount of current available to the car. E.g. in my personal setup, I regulate the amount of current during charging to ensure that the house use less than 10kW. And to charge when the price is the lowest.
BTW The reason you see me changing ChargerMaxCurrent so much now is because I've found this setting to be safe to use for testing when the car is not connected. It results in service bus events which I use when testing the development versions. After I completely got rid of the Tibber integration, these values doesn't seem to change any more.
I dont think you should be concerned here, your plan to do poll some endpoint less that others is fine, if data that you receive are more or less static, why polling so often. When it comes to GET chargers/{id}/state you will use same interval as before during charging, so there shouldn't be any difference.
OK. Then I think we skip the device- and state dependent and polling of GET chargers/{id}/state for now. Then every charger will be polled every 60 seconds.
This is good as it's most common for HA integration to only have one account-wide poll interval, so making this device and state specific, would be more work which delay the release.
Just for this part - probably misunderstanding, when I said "When it comes to GET chargers/{id}/state you will use same interval as before during charging, so there shouldn't be any difference", I meant no difference during charging since interval is the same, so shouldn't be any difference - in user experience.
While for all other parts, you should go with proposed intervals, that would be much better.
Especially authorize charge and setting cable lock is highly sought after features which is lacking from the public API. I have no immediate plans on removing them just yet and I'd like to discuss these with you later. Now we're focusing on the system for polling.
Yes, focus on polling, I will check on our side if there are replacements for those.
ChargerMaxCurrent or InstallationAvailableCurrent are frequently used by users to regulate the amount of current available to the car. E.g. in my personal setup, I regulate the amount of current during charging to ensure that the house use less than 10kW. And to charge when the price is the lowest.
So it means that all updates, sending commands coming from user adjusting values/clicking buttons, or those actions also could be part of an automation?
In general, sounds good, looking forward for further changes. Just let us know if you need any more details.
@ivastokic
There is one observation maybe you can sched some light on. I keep getting 500 Internal Server Error when issuing POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (DeauthorizeAndStop), which is one of the official commands documented in the API. The thing is that the command works, as is, the charger state change as a result of the command, despite it giving 500.
14:34:06.447 EVENT {'ChargerId': '{id}', 'StateId': '710 (ChargerOperationMode)', 'Timestamp': '2025-07-22T14:34:05.911552Z', 'ValueAsString': '3'}
14:34:06.447 Updating {id}.charger_operation_mode (ChargerOperationMode) = <str> Connected_Charging (was Connected_Requesting)
...
14:46:17.023 Command deauthorize_and_stop (10001)
14:46:17.023 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001'
14:46:17.379 RESPONSE 500 length 45
14:46:17.380 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (attempt 2)
14:46:17.585 RESPONSE 500 length 45
14:46:17.585 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (attempt 3)
14:46:17.798 RESPONSE 500 length 45
14:46:17.799 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (attempt 4)
14:46:17.984 RESPONSE 500 length 45
14:46:17.985 SLEEP for 0.06 seconds
14:46:18.229 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (attempt 5)
14:46:18.537 RESPONSE 500 length 45
14:46:18.537 SLEEP for 0.27 seconds
14:46:19.117 REQUEST POST to 'https://api.zaptec.com/api/chargers/{id}/SendCommand/10001' (attempt 6)
14:46:19.155 EVENT {'ChargerId': '{id}', 'StateId': '710 (ChargerOperationMode)', 'Timestamp': '2025-07-22T14:46:18.581584Z', 'ValueAsString': '5'}
14:46:19.155 Updating {id}.charger_operation_mode (ChargerOperationMode) = <str> Connected_Finished (was Connected_Charging)
PS! We retry the request on 500 Internal Error (with an exponential backoff), as many users are intermittently experiencing 500 from time to time. Retrying has been effective.
@sveinse could you also post a response body? Because it should have subcode in it.
@thecoldwine
{"Code":528,"Details":null,"StackTrace":null}
May I assume "DeviceCommandRejected" unless my reverse grepping is mistaken.
Two follow up questions:
- Is it unwise of us to retry on
POSTwhen it returns 500 ? I know that POST is intended to be idempotent, but that's not always the case. - When 500 is received, should we log it for the user (not just the development version)? It should be easy enough to add the data payload on 500 responses into the user's log.
@sveinse
- It depends. Device might be offline or in a state when it is not ready to accept commands. It might make sense to try again, but with a longer delay (say, try in 30 seconds), because internally we do retry ourselves towards the upstream service that issues a command.
- You have to follow subcodes. 528 is indeed
DeviceCommandRejectedand is thrown if there is a problem with a request itself. For any unknown issues we do throw 520ErrorCommunicatingWithDevice.
I will follow up with a team on making sure we're capturing as much of the context as we can in the error response body.