Rivian Auth Reference
Rivian does not publish a supported public owner API. Riviamigo follows the same
cloud API shape used by the unofficial Home Assistant Rivian integration and the
rivian-python-client package.
Upstream References
- Home Assistant integration:
https://github.com/bretterer/home-assistant-rivian - Client library pinned by that integration:
rivian-python-client[ble]==2.0.0 - Source file to compare when auth breaks:
rivian/rivian.py
Current Endpoints
- GraphQL gateway:
https://rivian.com/api/gql/gateway/graphql - Charging GraphQL:
https://rivian.com/api/gql/chrg/user/graphql - Vehicle state WebSocket:
wss://api.rivian.com/gql-consumer-subscriptions/graphql
Required Headers
Base GraphQL requests should include:
User-Agent: RivianApp/707 CFNetwork/1237 Darwin/20.4.0Accept: application/jsonContent-Type: application/jsonApollographql-Client-Name: com.rivian.ios.consumer-apollo-iosdc-cid: m-ios-<uuid>
After creating a CSRF session, login and OTP requests also include:
Csrf-Token: <csrfToken>A-Sess: <appSessionToken>
Authenticated GraphQL requests generally use:
A-Sess: <appSessionToken>U-Sess: <userSessionToken>Authorization: Bearer <accessToken>
The GraphQL WebSocket uses the graphql-transport-ws subprotocol and sends
u-sess in the connection_init payload.
Login Flow
- Call
CreateCSRFToken. - Save
csrfTokenandappSessionToken. - Call
Loginwith email/password and the CSRF/app-session headers. - If Rivian returns
MobileMFALoginResponse, saveotpTokenplus the CSRF session and ask the user for the MFA code. - Call
LoginWithOTPwith email,otpCode, andotpToken. - Save
accessToken,refreshToken,userSessionToken,appSessionToken,csrfToken, and the creation timestamp. - Call
getUserInfoagainst the same gateway to readcurrentUser.vehicles[].id,vin,name,vehicle.modelYear, andvehicle.model. /v1/vehicles/connectreturns those vehicle summaries. The browser must follow a successful connect by callingPOST /v1/vehicles, which encrypts and persists the temporary token bundle from Redis intoriviamigo.vehicle_credentialsand setsusers.default_vehicle_idif it is currently empty.
Refreshing credentials for an existing vehicle uses the same encrypted storage
path and immediately sends a worker-start command. This matters after a restore:
provider credentials are intentionally redacted from recovery packages, so the
vehicle can exist in PostgreSQL without a credential row. Startup still runs the
vehicle worker long enough to replace stale authorized/connected state with
an actionable needs_reauth status. After the user reconnects the Rivian
account, the supervisor replaces that completed worker and starts ingestion
immediately. A successful refresh should therefore be followed by worker health
and telemetry-timestamp checks, not only by an authorized database state.
Local Riviamigo Auth Gotcha
/v1/vehicles/connect is protected by Riviamigo's own JWT. A browser-side
401 Unauthorized on that route can mean the local 15-minute Riviamigo access
token expired before Rivian was contacted. The web API client retries protected
requests once after calling /v1/auth/refresh.
If the UI returns to "Add a Vehicle" after a successful Rivian login, check:
- Redis key
rivian:connect:<user_id>exists: Rivian auth succeeded but has not been persisted. riviamigo.vehicleshas no row for the user: the browser did not completePOST /v1/vehicles.users.default_vehicle_idis null: the dashboard will continue to show the empty vehicle state even though Rivian auth temporarily succeeded.