1) Which OAuth flow to use
For most owner projects, use Authorization Code flow. You do the one-time consent in a browser and then your backend refreshes access tokens using the refresh token.
2) Redirect URI rules (the #1 failure)
- Redirect URI must match Tesla app config exactly (scheme + host + path).
- Do not add/remove trailing slashes “later”.
- When in doubt, copy/paste the exact URL from your backend route into Tesla Developer Portal.
3) Refresh token rotation (the #2 failure)
When you refresh, Tesla returns a new refresh token. Store it and use it next time. If you keep using an old refresh token, you’ll eventually start seeing 401/403.
4) Fast 401/403 checklist
- Wrong region base URL (NA/EU/APAC) for Fleet API calls.
- Scopes mismatch (token valid but not authorized for endpoint).
- Refresh rotation not handled (old token reused).
- Two refresh calls running concurrently (one invalidates the other).
- Client credentials mismatch (wrong client_id/secret for that refresh token).
Minimal snippets
Token exchange (authorization_code)
curl -sS -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=AUTH_CODE_FROM_REDIRECT" \
-d "redirect_uri=https://yourdomain.com/callback" \
"https://auth.tesla.com/oauth2/v3/token"
Refresh (rotate refresh token)
curl -sS -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "refresh_token=YOUR_CURRENT_REFRESH_TOKEN" \
"https://auth.tesla.com/oauth2/v3/token"