Skip to content

Conversation

@spasdev
Copy link

@spasdev spasdev commented Nov 10, 2025

Since last week I experienced issue with the Zaptec charger.

Logs were showing entries this

"ERROR 2025/11/09 23:47:21 charge power: Get "https://api.zaptec.com/api/chargers/caaexxxxxxxxxxxxxa57-a45f-19bdssssssss/state": oauth2: cannot fetch token: 503 Service Unavailable Response: 503 Service Temporarily Unavailable503 Service Temporarily Unavailable nginx/1.29.0"

I observed the same issue at several Zaptec installation with EVCC. I reached out to Zaptec support and they pointed to a change in the authentication format.

From Zaptec Support :
"On Monday, we migrated our authentication solution and the Grant_Type was changed from password&username to password only.
Could this be the cause of your error?

https://docs.zaptec.com/docs/api-authentication#/

curl --location 'https://api.zaptec.com/oauth/token'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=password'
--data-urlencode 'username={[email protected]}'
--data-urlencode 'password={your_password}'
--data-urlencode 'scope=offline_access'
"

I made the change in the authentication format. It solved the issue at my installation and 2 others. No more authentication errors are thrown.

- Replace PasswordCredentialsToken with custom exchangePasswordCredentials
- Use grant_type=password with separate username, password, and scope parameters
- Resolves 503 Service Unavailable errors after Zaptec API migration
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Instead of hardcoding the “offline_access” scope, make the scope value configurable so future API changes don’t require a code update.
  • The custom token exchange duplicates HTTP client lookup logic; consider extracting that into a shared helper or leveraging the oauth2 library’s AuthStyle/Exchange directly.
  • On non-200 responses you only return resp.Status—consider reading and including the response body or adding retry logic for 503 errors to improve observability and resiliency.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Instead of hardcoding the “offline_access” scope, make the scope value configurable so future API changes don’t require a code update.
- The custom token exchange duplicates HTTP client lookup logic; consider extracting that into a shared helper or leveraging the oauth2 library’s AuthStyle/Exchange directly.
- On non-200 responses you only return `resp.Status`—consider reading and including the response body or adding retry logic for 503 errors to improve observability and resiliency.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@andig
Copy link
Member

andig commented Nov 10, 2025

Can you pls format your post?

@andig andig added the devices Specific device support label Nov 10, 2025
@andig
Copy link
Member

andig commented Nov 10, 2025

It's unlcear to me what this PR really does. According to Zaptec docs, username is required.

@andig andig marked this pull request as draft November 10, 2025 17:09
@spasdev
Copy link
Author

spasdev commented Nov 10, 2025

Can you pls format your post?

yes sorry, I overlooked that the copy/paste from email and errors brought some html tags

@andig
Copy link
Member

andig commented Nov 10, 2025

#25208 (comment)

@spasdev
Copy link
Author

spasdev commented Nov 10, 2025

It's unlcear to me what this PR really does. According to Zaptec docs, username is required.

yes, understand it is confusing as the support answer refers to a password.

In my first run I just implemented and directly what is asked here : https://docs.zaptec.com/docs/api-authentication

Maybe not the best approach.

Fortunately I found now a webarchive of the specification before the change.
So I compared
https://web.archive.org/web/20250619212829/https://docs.zaptec.com/docs/api-authentication
and the current one
https://docs.zaptec.com/docs/api-authentication

but I'm still not 100% sure to capture all the subtlety of the change. So I asked back the support. Will keep informed.
In the meantime I'm testing a version where the only change compared to the current version is to have a single scope to test if the issue is multi scope.

	Scopes: []string{
DELETE --> oidc.ScopeOpenID,
		oidc.ScopeOfflineAccess,
	},

apparently, the issue is popping up at other locations #25216 #25053

@spasdev
Copy link
Author

spasdev commented Nov 11, 2025

I have not yet received confirmation on the exact changes Zaptec made but I received this information

We also have a rate limit of 1 request per minute in the Auth endpoint currently, until everything runs again smoothly on our side. So this could be the main issue you're facing.

@spasdev
Copy link
Author

spasdev commented Nov 11, 2025

if anyone has more information please feel free to post it. On my side I did not yet get any clarification from Zaptec on the API change (if any).

@andig
Copy link
Member

andig commented Nov 12, 2025

Could you test your changes individually? No username vs. changed scopes? Which one is really effective? Username is required according to Zaptec docs. OIDC is not.

@spasdev
Copy link
Author

spasdev commented Nov 12, 2025

I tested both versions and both version worked. Having said that the original response from Zaptec support was in my view somehow misleading "Grant_Type was changed from password&username to password only". It requires clearly a username. And grant_type had, as far as I understand from webarchive, also before to be set to password.

My first version was to implement the parameters straight according to the current example (replace oc.PasswordCredentialsToken with own method).
My second version was to change the scope.
Since yesterday I'm using again the latest nightly build of EVCC and it runs also.
Thus, I have the impression that no changes were made to the API and that it was just "timing luck" that my changed version worked when I deployed it. As such original code and my versions are doing probably exactly the same (except for the scope). I checked the standard method and it also uses grant_type password. https://cs.opensource.google/go/x/oauth2/+/refs/tags/v0.33.0:oauth2.go;l=197

I'm in touch with the support but I'm having a hard time to make them state clearly that nothing changed and that the issue is/was just Zaptec internal. If I get this confirmation we can cancel this change.

Is someone still experiencing the issue after the restart of EVCC?

@andig
Copy link
Member

andig commented Nov 12, 2025

I tested both versions and both version worked.

If either works without the other, then non of the others is required, hence we don't need to change anything.

@andig andig closed this Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devices Specific device support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants