Developer API

Rivnly REST API

Pull your Rivian data into Grafana, Home Assistant, spreadsheets, or anything else. Create a scoped API key from the app settings and follow the reference below.

Rivnly API Reference

Base URL: https://app.rivnly.com

Authentication

All API endpoints require authentication via an API key passed in the Authorization header:

Authorization: Bearer rnly_your_api_key_here

API keys are created from the Rivnly settings page. Each key is scoped to the user who created it and can only access that user's vehicle data.

Scopes

Scope Access
read Vehicle state, drives, charging history, snapshots, maintenance
commands Send vehicle commands (wake, lock, frunk, etc.)

Rate Limiting

Each API key has a configurable rate limit (default: 60 requests per minute). When exceeded, the API returns 429 Too Many Requests.

Errors

All errors return JSON with an error field:

{ "error": "Not authenticated" }
Status Meaning
401 Missing or invalid API key
403 API key missing required scope
404 Resource not found
429 Rate limit exceeded

Vehicles

GET /api/vehicles

List all vehicles associated with your account.

Scope: read

Response:

[
  {
    "id": 1,
    "rivian_vehicle_id": "01-248753095",
    "vin": "7PDSGBBP5TN088960",
    "model": "R1S",
    "model_year": 2026,
    "trim_option": "R1S Tri",
    "exterior_color": "El Cap Granite paint",
    "interior_color": "Black Mountain + Brown Ash Wood",
    "wheel_option": "22\" Sport Dark",
    "drive_system": "Tri-motor AWD",
    "tonneau_option": null,
    "charge_port": "NACS",
    "max_vehicle_power": 215,
    "drive_modes": ["everyday", "sport", "distance", "winter", "off_road_auto"],
    "towing_drive_modes": ["everyday", "off_road_auto", "winter"],
    "ccc_capable": true,
    "ccc_ready": true,
    "ccc_enabled": true
  }
]

Note: Use the rivian_vehicle_id value as the :vehicle_id path parameter for all other endpoints.


Vehicle State

GET /api/vehicle/:vehicle_id/state

Fetch the current vehicle state from the Rivian API. Returns real-time data including battery, location, climate, doors/locks, and more.

Scope: read

Response:

{
  "data": {
    "vehicleState": {
      "batteryLevel": { "timeStamp": "...", "value": 72.5 },
      "batteryCapacity": { "value": 142.05 },
      "distanceToEmpty": { "timeStamp": "...", "value": 401 },
      "vehicleMileage": { "timeStamp": "...", "value": 735336 },
      "gnssLocation": { "latitude": 38.544, "longitude": -121.269, "timeStamp": "..." },
      "gnssSpeed": { "timeStamp": "...", "value": 0.0 },
      "powerState": { "timeStamp": "...", "value": "ready" },
      "gearStatus": { "timeStamp": "...", "value": "park" },
      "driveMode": { "timeStamp": "...", "value": "everyday" },
      "chargerState": { "timeStamp": "...", "value": "chrgr_sts_not_connected" },
      "cabinClimateInteriorTemperature": { "timeStamp": "...", "value": 22.5 },
      "doorFrontLeftLocked": { "timeStamp": "...", "value": "locked" },
      "...": "..."
    }
  },
  "_ws": {
    "cloud_is_online": false,
    "cloud_last_sync": "2026-04-14T14:59:34.512Z",
    "tire_pressure_psi": { "frontLeft": 47.9, "frontRight": 48.1, "rearLeft": 47.5, "rearRight": 47.8 },
    "ws_connected": true
  }
}

Data units (raw from Rivian API):

Field Unit Conversion
vehicleMileage meters / 1609.344 = miles
distanceToEmpty km * 0.621371 = miles
gnssSpeed m/s * 2.237 = mph, * 3.6 = km/h
gnssAltitude meters (MSL) * 3.28084 = feet
cabinClimate*Temperature Celsius * 9/5 + 32 = Fahrenheit
batteryLevel percentage 0-100
batteryCapacity kWh

GET /api/vehicle/:vehicle_id/state/history

Historical vehicle state snapshots from the database.

Scope: read

Query Parameters:

Parameter Type Default Description
hours integer 24 Number of hours of history to return

Response:

{
  "snapshots": [
    {
      "id": 12345,
      "captured_at": "2026-04-14T01:00:00+00:00",
      "battery_level": 54.3,
      "battery_capacity": 142.7,
      "distance_to_empty": 301,
      "vehicle_mileage": 735336,
      "latitude": 38.544,
      "longitude": -121.269,
      "altitude": 35.2,
      "speed": 0.0,
      "charger_state": "chrgr_sts_not_connected",
      "power_state": "ready",
      "drive_mode": "everyday",
      "gear_status": "park",
      "cabin_temp_interior": 22.5,
      "ota_current_version": "2026.03.0"
    }
  ]
}

Note: Snapshot data has already been converted: speed is in km/h, altitude is meters above sea level (MSL, geoid-corrected).

GET /api/vehicle/:vehicle_id/last-connection

Last cloud connection sync timestamp.

Scope: read

GET /api/vehicle/:vehicle_id/ota

OTA update details (current and available versions).

Scope: read

GET /api/vehicle/:vehicle_id/range

Estimated range at a given state of charge.

Scope: read

Query Parameters:

Parameter Type Default Description
soc float 80 State of charge percentage (0-100)

GET /api/vehicle/:vehicle_id/maintenance

Vehicle maintenance schedule and current mileage.

Scope: read

Response:

{
  "maintenance": { "...": "Rivian maintenance schedule JSON" },
  "model_year": 2026,
  "vehicle_name": "R1S",
  "trim": "R1S Tri",
  "vin": "7PDSGBBP5TN088960",
  "current_mileage_meters": 735336
}

GET /api/vehicle/:vehicle_id/enrollment-status

Check if a phone key is enrolled for vehicle commands.

Scope: read

Response:

{ "enrolled": true }

Drive Sessions

GET /api/vehicle/:vehicle_id/drives

List drive sessions, newest first (limit 50).

Scope: read

Response:

{
  "drives": [
    {
      "id": 42,
      "start_time": "2026-04-13T16:02:09+00:00",
      "end_time": "2026-04-13T16:19:13+00:00",
      "duration_seconds": 1024,
      "distance_meters": 19288,
      "distance_miles": 12.0,
      "start_battery": 47.6,
      "end_battery": 42.6,
      "energy_used_kwh": 7.1,
      "drive_mode": "everyday",
      "start_latitude": 38.544,
      "start_longitude": -121.269,
      "end_latitude": 38.574,
      "end_longitude": -121.408
    }
  ]
}

GET /api/vehicle/:vehicle_id/drives/:drive_id

Single drive with GPS route, speed/elevation data, and computed stats.

Scope: read

Response:

{
  "drive": { "...": "same fields as list above" },
  "stats": {
    "avg_speed_kmh": 62.4,
    "max_speed_kmh": 118.1,
    "avg_cabin_temp_c": 22.5,
    "min_elevation_m": 6.2,
    "max_elevation_m": 35.1,
    "snapshot_count": 65
  },
  "snapshots": [
    {
      "captured_at": "2026-04-13T16:02:09+00:00",
      "latitude": 38.544,
      "longitude": -121.269,
      "speed": 0.0,
      "altitude": 35.2,
      "battery_level": 47.6,
      "gear_status": "park",
      "...": "..."
    }
  ]
}

Charging Sessions

GET /api/vehicle/:vehicle_id/charging/history

All completed charging sessions with aggregate totals.

Scope: read

Response:

{
  "sessions": [
    {
      "id": 2006,
      "start_time": "2026-04-13T20:10:16+00:00",
      "end_time": "2026-04-13T20:27:45+00:00",
      "duration_seconds": 1049,
      "total_energy_kwh": 8.715,
      "range_added_km": 37.0,
      "start_battery": 38.3,
      "end_battery": 44.6,
      "cost_total": 6.27,
      "cost_currency": "USD",
      "vendor": "Tesla",
      "city": "Folsom",
      "is_home_charger": false,
      "is_public": true,
      "source": "rivian_api"
    }
  ],
  "totals": {
    "session_count": 25,
    "total_energy_kwh": 842.5,
    "total_cost": 127.33,
    "total_range_added_miles": 2104.7
  }
}

GET /api/vehicle/:vehicle_id/charging/session/:session_id

Single charging session detail with battery snapshots captured during the charge window.

Scope: read

Response:

{
  "session": { "...": "same fields as list above" },
  "snapshots": [
    {
      "captured_at": "2026-04-13T20:10:32+00:00",
      "battery_level": 38.3,
      "charger_state": "charging_active",
      "...": "..."
    }
  ]
}

GET /api/vehicle/:vehicle_id/charging/live

Live charging data (when actively charging) and last completed session summary.

Scope: read

Response:

{
  "data": {
    "liveSession": null,
    "chartData": null,
    "lastSession": {
      "id": 2006,
      "total_energy_kwh": 8.715,
      "range_added_km": 37.0,
      "...": "..."
    }
  }
}

GET /api/vehicle/:vehicle_id/charging/schedule

Vehicle charging schedule configuration.

Scope: read


Vehicle Commands

Important: Most commands require BLE proximity to the vehicle. The API will accept the command, but execution requires a Bluetooth connection. WAKE_VEHICLE may work remotely.

POST /api/vehicle/:vehicle_id/command

Send a signed vehicle command.

Scope: commands

Request Body:

{ "command": "WAKE_VEHICLE" }

Valid Commands:

Command Description
WAKE_VEHICLE Wake the vehicle (may work remotely)
OPEN_FRUNK Open the front trunk
CLOSE_FRUNK Close the front trunk
OPEN_ALL_WINDOWS Open all windows
CLOSE_ALL_WINDOWS Close all windows
UNLOCK_ALL_CLOSURES Unlock all doors
LOCK_ALL_CLOSURES Lock all doors
ENABLE_GEAR_GUARD_VIDEO Enable Gear Guard video recording
DISABLE_GEAR_GUARD_VIDEO Disable Gear Guard video recording
HONK_AND_FLASH_LIGHTS Honk horn and flash lights
OPEN_TONNEAU_COVER Open tonneau cover (R1T only)
CLOSE_TONNEAU_COVER Close tonneau cover (R1T only)

Response:

{
  "data": {
    "sendVehicleCommand": {
      "id": "cmd-abc123",
      "command": "WAKE_VEHICLE",
      "state": 0
    }
  }
}

GET /api/vehicle/:vehicle_id/command/:command_id/status

Check the execution status of a previously sent command.

Scope: commands

Response:

{
  "data": {
    "getVehicleCommand": {
      "id": "cmd-abc123",
      "command": "WAKE_VEHICLE",
      "state": 0
    }
  }
}

state: 0 indicates the command completed successfully.

POST /api/vehicle/:vehicle_id/enroll-phone

Enroll a virtual phone key for HMAC command signing. Required once before sending commands.

Scope: commands


Examples

cURL: Get vehicle list

curl -H "Authorization: Bearer rnly_your_key_here" \
  https://app.rivnly.com/api/vehicles

cURL: Get drive history

curl -H "Authorization: Bearer rnly_your_key_here" \
  https://app.rivnly.com/api/vehicle/01-248753095/drives

cURL: Get current vehicle state

curl -H "Authorization: Bearer rnly_your_key_here" \
  https://app.rivnly.com/api/vehicle/01-248753095/state

Python

import requests

API_KEY = "rnly_your_key_here"
BASE_URL = "https://app.rivnly.com"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# List vehicles
vehicles = requests.get(f"{BASE_URL}/api/vehicles", headers=HEADERS).json()
vehicle_id = vehicles[0]["rivian_vehicle_id"]

# Get current state
state = requests.get(f"{BASE_URL}/api/vehicle/{vehicle_id}/state", headers=HEADERS).json()
battery = state["data"]["vehicleState"]["batteryLevel"]["value"]
print(f"Battery: {battery}%")

# Get drive history
drives = requests.get(f"{BASE_URL}/api/vehicle/{vehicle_id}/drives", headers=HEADERS).json()
for drive in drives["drives"][:5]:
    miles = drive.get("distance_miles", 0)
    kwh = drive.get("energy_used_kwh", 0)
    print(f"Drive {drive['id']}: {miles} mi, {kwh} kWh")

JavaScript

const API_KEY = 'rnly_your_key_here';
const BASE = 'https://app.rivnly.com';
const headers = { Authorization: `Bearer ${API_KEY}` };

const vehicles = await fetch(`${BASE}/api/vehicles`, { headers }).then(r => r.json());
const vehicleId = vehicles[0].rivian_vehicle_id;

const state = await fetch(`${BASE}/api/vehicle/${vehicleId}/state`, { headers }).then(r => r.json());
console.log('Battery:', state.data.vehicleState.batteryLevel.value + '%');