NAV

comma API spec

Base URL: https://api.commadotai.com/

Definitions

Dongle ID

A dongle ID is an 16-character alphanumeric device identifier. Each comma device has a unique dongle ID.

Segment

A segment is one minute of driving. openpilot rotates log and camera files at this interval. Segments are numbered in a 0-indexed fashion.

Segment names are of the form dongle_id|YYYY-MM-DD--HH-MM-SS--N where N is the segment number. For example, 0375fdf7b1ce594d|2019-05-21--23-17-14--0.

Route

A route is a sequence of segments recorded between car ignition and power-down. Route names are of the form dongle_id|YYYY-MM-DD--HH-MM-SS. For example, 0375fdf7b1ce594d|2019-05-21--23-17-14.

Authentication

Include a JWT header of the following format in order to access authenticated endpoints:

curl -H 'Authorization: JWT {{token}}' https://api.commadotai.com/

Token can be acquired at jwt.comma.ai

Enter your token here to autofill code blocks:

Response Codes

We use conventional HTTP response codes to signal success or failure of API requests.

200 - OK
400 - Bad Request: Likely due to an invalid or missing parameter.
401 - Unauthorized: JWT token invalid.
403 - Forbidden. Authenticated user lacks access to desired entity.
404 - Not Found: Requested entity does not exist.
409 - Conflict: Entity already exists.
429 - Too Many Requests: Too many requests, too quickly. Please use exponential backoff and see per-endpoint rate limit documentation.

Account

Profile

GET /v1/me/

Returns information about the authenticated user

curl https://api.commadotai.com/v1/me/ -H 'Authorization: JWT {{token}}'
{
  "email": "commaphone3@gmail.com",
  "id": "2e9eeac96ea4e6a6",
  "points": 34933,
  "regdate": 1465103707,
  "superuser": false,
  "username": "joeyjoejoe"
}




Response

Key Type Description
"email" string Your email
"id" (string) Dongle ID
"points" (integer) Number of comma points
"regdate" (integer) Seconds since epoch at time of registration
"superuser" (bool) Apply for superuser here
"username" (string) Your username

Devices

GET /v1/me/devices/

List devices owned or readable by authenticated user

curl https://api.commadotai.com/v1/me/devices/ -H 'Authorization: JWT {{token}}'





Response

[
  {
    "alias": "Comma EON",
    "device_type": "neo",
    "dongle_id": "4bba516fb4439b31",
    "is_owner": true,
    "is_paired": true,
    "last_gps_accuracy": 12,
    "last_gps_bearing": 0,
    "last_gps_lat": 32.0,
    "last_gps_lng": -117.0,
    "last_gps_speed": 0,
    "last_gps_time": 1558583671000,
    "last_segment_create_time": 1557180193,
    "last_segment_utc_millis": 1554179182574,
    "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLI++RMXz29fBPNdECbCL8SGQ1+O/y1xhLsm/XsApxlghsKiWFSXiLJbHkHFOhQb6F421pVMZI0NtVXK5hUmwaAYLVg644/sLv/J32iW2vvdntT6GRTJxJr4LvbuXuBggW2sIYINFOOKng71CO5BxUNn+WNmeYFSqblFi4HjIuGbUZABuF9t0nkjMMVDZm9pTeeWqJtC4BxlACmJPA/88bdsiq4VDZ51yWqXxKJAq1HpG8RXpBs2leNQfnqF/mwtAkSeatqJYTjNAv77lFVg0rOQ6XjDLGdtRiloD+mNnJa1CJF4NiUG7hY/mdmolE4ML9W8YYX1aHNROmZApAt+Bn root@localhost\n",
  },
  {
    "alias": "Toyota RAV4 EON Gold",
    "device_type": "neo",
    "dongle_id": "b0c9d2329ad1606b",
    "is_owner": false,
    "is_paired": true,
    "last_gps_accuracy": 10,
    "last_gps_bearing": 323,
    "last_gps_lat": 32.0,
    "last_gps_lng": -117.0,
    "last_gps_speed": 26.64,
    "last_gps_time": 1558736867000,
    "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUl0gKppV0TivHeL3PPqHeA2boPhKleJNdNWd5OeOhcD5N0Wsk9DLI/iBhbM1Q+LfJJsjBoJ+V/Hs9sSnIS04nuwaQMoj75gV+HwmVfBHY+UnGKCfpLpW7PCHgeReeUKOUZzTrrxp67NJaOQtdokq2oTlX4OPMzDncNJQAECnFz8DkGQMjapJVa6ctNuANaJscjlwokz4TYHlQAktb7WZoi4iRJMi6bR6HSb3R7uflrUbnS5OyebKLr6ZbhHPIy22rILXju/15XRhRPxfAjOPBXg+/WFwSBb3j6bL6TLbShXrJOsV6NrN7+Z0C3V6ZeH7SXl8Cua7FV0l7XodkDXaf root@localhost\n",
    "last_segment_create_time": 1557180193,
    "last_segment_utc_millis": 1554179182574
  }
]

Response

JSON array of devices, sorted by key "last_segment_utc_millis" descending

Key Type Description
"dongle_id" (string) see Dongle ID
"alias" (string) Globally unique device nickname
"is_paired" (bool) Device has an owner
"is_owner" (bool) Authed user has write-access to device
"public_key" (string) 2048-bit public RSA key
"device_type" (string) one of ("neo", "panda", "app")
"last_gps_time" (integer) Milliseconds since epoch of last gps. Updates upon successful call to device location endpoint
"last_gps_lat" (float) Latitude of last location
"last_gps_lng" (float) Longitude of last location
"last_gps_accuracy" (float) Accuracy (m) of last location
"last_gps_speed" (float) Speed (m/s) at last location
"last_gps_bearing" (float) Direction of last location in degrees from north
"last_segment_create_time" (integer) Seconds since epoch of most recent call to Upload URL for a segment
"last_segment_utc_millis" (integer) Milliseconds since epoch of most recent segment start time, from GPS.

Device

Device Info

GET /v1.1/devices/:dongle_id/

Returns an object representing a comma device.

curl https://api.commadotai.com/v1.1/devices/0375fdf7b1ce594d/ -H 'Authorization: JWT {{token}}'




Response

{
  "dongle_id": "0375fdf7b1ce594d",
  "alias": "Accord EON Gold",
  "is_paired": true,
  "is_owner": false,
  "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDy3qndOTobXV/f99QBJasvpwYBi357SP9wTZ1QTaezlv7us2zJNRrkZZU6Myu8BQKAoaUfE8ttWUMcj+/U94ZfYrCKQYv7lKuxAkkCWrYxRy7DfrWJNoq43zHIoaBAbpEXigJMhR2VmKwM0uPw2TFhXVTjeF+o77zOZYjxQUTU5BsQGR4CQMd2keuB6pjHua2VBP9mmdDksWg5fXZWo7RbwzZaLeDJY/9yI5QguqivGnYA6QM+9DPQlfbQ8PtxKuwQSiHTBvrxn+nzJKNuGlyxzjr1ca1uRZtV86I22mphn1rrYOg4Rb19tIM+bgmwZWOFu2yK/wRgFMnmcX4KhiQZ root@localhost\n",
  "device_type": "neo",
  "last_gps_time": 1558595762000,
  "last_gps_lat": 32.0,
  "last_gps_lng": -117.0,
  "last_gps_accuracy": 3,
  "last_gps_speed": 0,
  "last_gps_bearing": 0
}

Response

Key Type Description
"dongle_id" (string) see Dongle ID
"alias" (string) Globally unique device nickname
"is_paired" (bool) Device has an owner
"is_owner" (bool) Authed user has write-access to device
"public_key" (string) 2048-bit public RSA key
"device_type" (string) one of ("neo", "panda", "app")
"last_gps_time" (integer) Milliseconds since epoch of last gps. Updates upon successful call to device location endpoint
"last_gps_lat" (float) Latitude of last location
"last_gps_lng" (float) Longitude of last location
"last_gps_accuracy" (float) Accuracy (m) of last location
"last_gps_speed" (float) Speed (m/s) at last location
"last_gps_bearing" (float) Direction of last location in degrees from north

Update device properties

PATCH /v1/devices/:dongle_id/

Update device alias

alias (string): device alias shown on https://my.comma.ai and the comma connect app

curl -X PATCH 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/' \
-d '{"alias": "new_alias"}' \
-H 'Authorization: JWT {{token}}'

Response

Identical to Device Info but reflects updated fields.

Device location

GET /v1/devices/:dongle_id/location

Returns a gpsLocation ZMQ packet from the device. The API server queries Athena and caches the location for the Device Info response.

curl 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/location' \
-H 'Authorization: JWT {{token}}'

Response





{
  "dongle_id": "02ec6bea180a4d36",
  "lat": 32.0,
  "lng": -117.0,
  "time": 1558595762000,
  "speed": 0.0,
  "bearing": 0.0
}

Response

Key Type Description
"dongle_id" (string) see Dongle ID
"lat" (float) Latitude, degrees
"lng" (float) Longitude, degrees
"time" (integer) Milliseconds since epoch
"accuracy" (float) Accuracy (m)
"speed" (float) Speed (m/s)
"bearing" (float) Direction in degrees from north

Pair EON

POST https://api.commadotai.com/v2/pilotpair/

Pair a comma EON to authenticated user's account.

URLEncoded Request Body

Key Description
pair_token JWT Token signed by your EON private key containing payload {"identity": <dongle-id>, "pair": true}
curl -F 'pair_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImZvbyIsImlhdCI6MTU2MDU0OTM0MSwibmJmIjoxNTYwNTQ5MzQxLCJleHAiOjE1OTIwODUzNDF9.peoXbapsvT-W2dpNuHscJE6fqeaHtlB8owbTddzSkV0' https://api.commadotai.com/v2/pilotpair/ \
-H 'Authorization: JWT {{token}}'

Response

{"first_pair": true}

Response

Key Type Description
"first_pair" (string) True if the device was unpaired prior to this call. False if the device was previously paired by authenticated user.

Unpair device

POST /v1/devices/:dongle_id/unpair

Unpair a device. Authed user must be device owner to perform. (to check ownership, see Device Info).

curl -X POST 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/unpair' \
-H 'Authorization: JWT {{token}}'

Response





{"success": 1}

Response "success" (integer): 1 if device is unpaired. 0 if device type is not one of ("neo", "panda").

Grant device read permissions to user

POST /v1/devices/:dongle_id/add_user

Grant read permissions to a user by email. Authed user must be device owner to perform. (to check ownership, see Device Info). If multiple users are attached to an email address, the device is shared with all users.

curl -X POST 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/add_user' \
-d '{"email": "mycommafriend@gmail.com"}' \
-H 'Content-Type: application/json' \
-H 'Authorization: JWT {{token}}'

Response





{"success": 1}

Remove device read permissions from user

POST /v1/devices/:dongle_id/del_user

Remove read permissions from a user by email. Authed user must be device owner to perform. (to check ownership, see Device Info). If multiple users are attached to an email address, the device removed from all users.

curl -X POST 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/del_user' \
-d '{"email": "mycommaenemy@gmail.com"}' \
-H 'Content-Type: application/json' \
-H 'Authorization: JWT {{token}}'

Response





{"success": 1}

Device driving statistics

GET /v1.1/devices/:dongle_id/stats

Returns aggregate driving statistics for a device

curl 'https://api.commadotai.com/v1.1/devices/02ec6bea180a4d36/stats' \
-H 'Authorization: JWT {{token}}'

Response

{
  "all": {
    "distance": 13026.936680094295,
    "minutes": 23809,
    "routes": 1349
  },
  "week": {
    "distance": 105.20453522778553,
    "minutes": 372,
    "routes": 28
  }
}

Response

JSON object with keys "all" and "week", each of which has this format:

Key Type Description
"distance" (float) Total miles driven in time period
"minutes" (integer) Total minutes driven in time period
"routes" (integer) Count of routes in time period

Device users

GET /v1/devices/:dongle_id/users

List users with access to a device

curl 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/users' \
-H 'Authorization: JWT {{token}}'

Response

[
  {
    "email": "deviceowner@comma.ai",
    "permission": "owner"
  },
  {
    "email": "devicereader@comma.ai",
    "permission": "read_access"
  }
]

Response

JSON array of user objects.

Key Type Description
email string User email
permission string Device permission, one of ("owner", "read_access")

Device boot logs

GET /v1/devices/:dongle_id/bootlogs

Returns most recent bootlogs uploaded from a device.

curl 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/bootlogs' \
-H 'Authorization: JWT {{token}}'

Response

[
  "https://commadata2.blob.core.windows.net/commadata2/02ec6bea180a4d36/boot/2019-10-14--09-47-45.bz2?se=2019-10-16T17%3A52%3A03Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3D02ec6bea180a4d36_boot_2019-10-14--09-47-45.bz2&sig=sig/4%3D"
]

Response

JSON array of URLs of bootlog files. Files are available at each URL for one hour after time of API call.

Device crash logs

GET /v1/devices/:dongle_id/crashlogs

Returns most recent crashlogs uploaded from a device.

curl 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/crashlogs' \
-H 'Authorization: JWT {{token}}'

Response

[
  "https://commadata2.blob.core.windows.net/commadata2/02ec6bea180a4d36/crash/2019-10-14--09-47-45.bz2?se=2019-10-16T17%3A52%3A03Z&sp=r&sv=2018-03-28&sr=b&rscd=attachment%3B%20filename%3D02ec6bea180a4d36_crash_2019-10-14--09-47-45.bz2&sig=sig/4%3D"
]

Response

JSON array of URLs of crashlog files. Files are available at each URL for one hour after time of API call.

Routes

Segments

GET /v1/devices/:dongle_id/segments

Returns time-sorted list of segments, each of which includes basic metadata derived from openpilot log.

curl 'https://api.commadotai.com/v1/devices/02ec6bea180a4d36/segments?from=1558508400000&to=1559718000000' \
-H 'Authorization: JWT {{token}}'

Parameters

from required

The lower bound on the start time of returned segments, in milliseconds since epoch.

to optional

The upper bound on end time of returned segments, in milliseconds since epoch. If omitted, defaults to now.

[
  {
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--0",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "number": 0,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "start_time_utc_millis": 1558505835614,
    "proc_dcamera": -1,
    "radar": false,
    "create_time": 1558505900,
    "hpgps": true,
    "end_time_utc_millis": 1558505895587,
    "end_lng": -117.0,
    "start_lng": -117.0,
    "passive": false,
    "proc_log": 40,
    "version": "0.5.12",
    "git_branch": "master",
    "end_lat": 32.0,
    "proc_camera": 40,
    "devicetype": 3,
    "start_lat": 32.0,
    "events_json": "[{\"data\": {\"pre_soft_disable\": false, \"end_offset_nanos\": 464369, \"alertSize\": 2, \"end_time\": \"466342645882391\", \"alertType\": \"startup\", \"end_route_offset_millis\": 15199, \"end_route_offset_nanos\": 464369, \"should_take_control\": false, \"end_offset_millis\": 15199, \"alertText1\": \"Be ready to take over at any time\", \"alertStatus\": 0, \"alertText2\": \"Always keep hands on wheel and eyes on road\"}, \"route_offset_nanos\": 817760, \"offset_millis\": 237, \"time\": \"466327684235782\", \"type\": \"alert\", \"offset_nanos\": 817760, \"route_offset_millis\": 237}]",
    "git_dirty": true,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/aaaaaaa_2019-05-21--23-17-14/0",
    "length": 0.00179515,
    "dongle_id": "0375fdf7b1ce594d",
    "can": true,
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2"
  }
]

Response

JSON array of segment objects. Each segment has the following keys:

Key Type Description
"git_remote" string Git remote from openpilot log InitData
"start_time_utc_millis" integer Milliseconds since epoch of segment start time, from GPS
"number" integer Segment number
"proc_dcamera" integer Driver camera file status. See Segment File Status below
"radar" boolean True if segment contains radar tracks in CAN
"create_time" integer time of upload_url call for first file uploaded of segment
"hpgps" boolean True if segment has ublox packets
"end_time_utc_millis" integer Milliseconds since epoch of segment end time, from GPS
"end_lng" float Last longitude recorded in segment, from GPS
"start_lng" float First longitude recorded in segment, from GPS
"passive" boolean True if openpilot was running in passive mode. From openpilot log InitData
"canonical_name" string Segment name
"proc_log" Log file status. See Segment File Status below
"version" string Version string from openpilot log InitData
"git_branch" string Git branch from openpilot log InitData
"end_lat" float Last latitude recorded in segment from GPS
"proc_camera" Road camera file status. See Segment File Status below
"canonical_route_name" string Route name
"devicetype" integer 3 is EON
"start_lat" float First latitude recorded in segment from GPS
"git_dirty" boolean Git dirty flag from openpilot log InitData
"url" string Signed URL from which route.coords and jpegs can be downloaded (see Derived Data)
"length" float Sum of distances between GPS points, miles
"dongle_id" string Dongle ID
"can" boolean True if log has at least 1 can message
"git_commit" string Git commit from openpilot log InitData

Disengagement event

{
  "data": {
    "is_planned": false
  },
  "route_offset_nanos": 985946,
  "offset_millis": 45087,
  "time": "161093962680481",
  "type": "disengage",
  "offset_nanos": 942170,
  "route_offset_millis": 525093
}

"events_json" JSON array of event objects (is string encoded). Four types:

Engagement event

{
  "route_offset_nanos": 232202,
  "offset_millis": 12963,
  "time": "160941836926737",
  "type": "engage",
  "offset_nanos": 100204,
  "route_offset_millis": 372968
}

Alert event

{
  "data": {
    "pre_soft_disable": false,
    "end_offset_nanos": 824459,
    "alertSize": 2,
    "end_time": "156946181483417",
    "alertType": "steerSaturated",
    "end_route_offset_millis": 532376,
    "end_route_offset_nanos": 180003,
    "should_take_control": true,
    "end_offset_millis": 52400,
    "alertText1": "TAKE CONTROL",
    "alertStatus": 1,
    "alertText2": "Turn Exceeds Steering Limit"
  },
  "route_offset_nanos": 205578,
  "offset_millis": 47070,
  "time": "156940851508992",
  "type": "alert",
  "offset_nanos": 850034,
  "route_offset_millis": 527046
}

Steer override event

{
  "data": {
    "is_planned": false,
    "end_route_offset_millis": 877196,
    "end_time": "161446064800451",
    "end_offset_millis": 37255,
    "end_offset_nanos": 521861,
    "end_route_offset_nanos": 105916
  },
  "route_offset_nanos": 105243,
  "offset_millis": 26305,
  "time": "161435114799778",
  "type": "disengage_steer",
  "offset_nanos": 521188,
  "route_offset_millis": 866246
}

Note: The bits is_planned and pre_soft_disable are set in pipeline based on temporal correspondence with an alert for which we expect a disengagement.

Segment File Status

status code
upload_url_sent 0
received 10
enqueued 20
processing 30
processed 40

Route Info

GET /v1/route/:route_name/

Returns information about the provided route. Authenticated user must have ownership of or read access to device from which route was uploaded.

curl https://api.commadotai.com/v1/route/99c94dc769b5d96e\|2019-05-17--17-31-58/ \
-H 'Authorization: JWT {{token}}'

Response

{
  "git_remote": "git@github.com:commaai/openpilot.git",
  "start_lat": 32.0,
  "hpgps": true,
  "create_time": 1558654768,
  "maxdcamera": 2,
  "user_id": null,
  "end_lng": -117.0,
  "start_lng": -117.0,
  "passive": false,
  "platform": "HONDA CIVIC 2016 TOURING",
  "version": "0.5.12",
  "end_lat": 32.0,
  "git_branch": "devel",
  "maxcamera": 2,
  "proclog": 2,
  "maxlog": 2,
  "devicetype": 3,
  "proccamera": 2,
  "radar": true,
  "git_dirty": true,
  "init_logmonotime": 1932707747489,
  "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/99c94dc769b5d96e/aaaaaaaaa_2019-05-17--17-31-58",
  "length": 0,
  "dongle_id": "99c94dc769b5d96e",
  "can": true,
  "git_commit": "39448abbb5bfc7ac1ae6424cd90b94a475ca12fa",
  "fullname": "99c94dc769b5d96e|2019-05-17--17-31-58"
}




Response

Key Type Description
"git_remote" string Git remote from openpilot log InitData
"radar" boolean True if any segment in route contains radar tracks in CAN
"create_time" integer time of upload_url call for first file uploaded of route
"hpgps" boolean True if any segment in route has ublox packets
"end_lng" float Last longitude recorded in route, from GPS
"start_lng" float First longitude recorded in route, from GPS
"passive" boolean True if openpilot was running in passive mode. From openpilot log InitData
"version" string Version string from openpilot log InitData
"git_branch" string Git branch from openpilot log InitData
"end_lat" float Last latitude recorded in route from GPS
"fullname" string Route name
"devicetype" integer 3 is EON
"start_lat" float First latitude recorded in route from GPS
"git_dirty" boolean Git dirty flag from openpilot log InitData
"init_logmonotime" integer Minimum logMonoTime from openpilot log
"url" string Signed URL from which route.coords and jpegs can be downloaded (see Derived Data)
"length" float Sum of distances between GPS points, miles
"dongle_id" string Dongle ID
"can" boolean True if log has at least 1 can message
"git_commit" string Git commit from openpilot log InitData
"user_id" string User ID of device owner
"maxlog" integer Maximum log segment number uploaded
"proclog" integer Maximum log segment number processed
"maxcamera" integer Maximum camera segment number uploaded
"proccamera" integer Maximum camera segment number processed
"maxdcamera" integer Maximum front camera segment number uploaded

Route Segments

GET /v1/route/:route_name/segments

Returns list of segments comprising a route. Authenticated user must have ownership of or read access to device from which route was uploaded.

curl https://api.commadotai.com/v1/route/0375fdf7b1ce594d\|2019-05-21--23-17-14/segments \
-H 'Authorization: JWT {{token}}'

Response

[
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--5",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558506455,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7416,
    "end_lng": -117.18,
    "end_time_utc_millis": 1558506159491,
    "events_json": "[]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.0267973,
    "number": 5,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7415,
    "start_lng": -117.18,
    "start_time_utc_millis": 1558506135585,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/5",
    "version": "0.5.12"
  },
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--4",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558506337,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7414,
    "end_lng": -117.18,
    "end_time_utc_millis": 1558506135580,
    "events_json": "[]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.895458,
    "number": 4,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7309,
    "start_lng": -117.171,
    "start_time_utc_millis": 1558506075584,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/4",
    "version": "0.5.12"
  },
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--3",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558506214,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7304,
    "end_lng": -117.17,
    "end_time_utc_millis": 1558506075581,
    "events_json": "[]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.51377,
    "number": 3,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7258,
    "start_lng": -117.167,
    "start_time_utc_millis": 1558506015585,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/3",
    "version": "0.5.12"
  },
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--2",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558506095,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7258,
    "end_lng": -117.167,
    "end_time_utc_millis": 1558506015584,
    "events_json": "[]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.275832,
    "number": 2,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7218,
    "start_lng": -117.166,
    "start_time_utc_millis": 1558505955274,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/2",
    "version": "0.5.12"
  },
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--1",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558505980,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7217,
    "end_lng": -117.166,
    "end_time_utc_millis": 1558505955571,
    "events_json": "[]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.0933126,
    "number": 1,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7202,
    "start_lng": -117.167,
    "start_time_utc_millis": 1558505895585,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/1",
    "version": "0.5.12"
  },
  {
    "can": true,
    "canonical_name": "0375fdf7b1ce594d|2019-05-21--23-17-14--0",
    "canonical_route_name": "0375fdf7b1ce594d|2019-05-21--23-17-14",
    "create_time": 1558505900,
    "devicetype": 3,
    "dongle_id": "0375fdf7b1ce594d",
    "end_lat": 32.7202,
    "end_lng": -117.167,
    "end_time_utc_millis": 1558505895587,
    "events_json": "[{\"data\": {\"pre_soft_disable\": false, \"end_offset_nanos\": 464369, \"alertSize\": 2, \"end_time\": \"466342645882391\", \"alertType\": \"startup\", \"end_route_offset_millis\": 15199, \"end_route_offset_nanos\": 464369, \"should_take_control\": false, \"end_offset_millis\": 15199, \"alertText1\": \"Be ready to take over at any time\", \"alertStatus\": 0, \"alertText2\": \"Always keep hands on wheel and eyes on road\"}, \"route_offset_nanos\": 817760, \"offset_millis\": 237, \"time\": \"466327684235782\", \"type\": \"alert\", \"offset_nanos\": 817760, \"route_offset_millis\": 237}]",
    "git_branch": "master",
    "git_commit": "8b7b90ce71eda504902f3a3c183ff5151bfac0d2",
    "git_dirty": true,
    "git_remote": "git@github.com:commaai/openpilot.git",
    "hpgps": true,
    "length": 0.00179515,
    "number": 0,
    "passive": false,
    "proc_camera": 40,
    "proc_dcamera": -1,
    "proc_log": 40,
    "proc_qlog": null,
    "radar": false,
    "start_lat": 32.7231,
    "start_lng": -117.169,
    "start_time_utc_millis": 1558505835614,
    "url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/0375fdf7b1ce594d/39b636f2cde7d3e78e47d30c99fcdb62_2019-05-21--23-17-14/0",
    "version": "0.5.12"
  }
]





Response

Returns JSON array of segments. See Segments

Route Manifest

GET /v1/route/:route_name/manifest

Lists files uploaded for a route.

curl https://api.commadotai.com/v1/route/cce908f7eb8db67d\|2019-10-12--10-41-14/manifest \
-H 'Authorization: JWT {{token}}'

Response

[
  {
    "file": "qlog.bz2",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/0/qlog.bz2",
    "last_modified": "2019-10-12 17:42:25",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--0",
    "size": 321044
  },
  {
    "file": "qlog.bz2",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/1/qlog.bz2",
    "last_modified": "2019-10-12 17:43:51",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--1",
    "size": 299785
  },
  {
    "file": "dcamera.hevc",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/0/dcamera.hevc",
    "last_modified": "2019-10-12 18:23:49",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--0",
    "size": 17338425
  },
  {
    "file": "fcamera.hevc",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/0/fcamera.hevc",
    "last_modified": "2019-10-12 17:53:25",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--0",
    "size": 34631930
  },
  {
    "file": "rlog.bz2",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/0/rlog.bz2",
    "last_modified": "2019-10-12 17:43:45",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--0",
    "size": 4733423
  },
  {
    "file": "dcamera.hevc",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/1/dcamera.hevc",
    "last_modified": "2019-10-12 18:39:39",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--1",
    "size": 17281817
  },
  {
    "file": "fcamera.hevc",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/1/fcamera.hevc",
    "last_modified": "2019-10-12 18:34:48",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--1",
    "size": 34561050
  },
  {
    "file": "rlog.bz2",
    "key": "cce908f7eb8db67d/2019-10-12--10-41-14/1/rlog.bz2",
    "last_modified": "2019-10-12 18:25:08",
    "segment": "cce908f7eb8db67d|2019-10-12--10-41-14--1",
    "size": 4747911
  }
]





Response

JSON array of file objects

Key Type Description
"file" (string) File name
"key" (string) File key
"last_modified" (string) File upload time, UTC
"segment" (string) Name of segment in which file was produced
"size" (integer) Number of bytes in file

Raw driving data

Files

GET /v1/route/:route_name/files

Retrieve uploaded files for a route. Calls to this API are rate limited to 5 per minute.

curl https://api.commadotai.com/v1/route/99c94dc769b5d96e\|2019-05-17--17-31-58/files \
-H 'Authorization: JWT {{token}}'

Response





{
  "cameras": [
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/0/fcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--0--fcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=WHR7QdvxYs%2BhsM5b1inMCpgAErknsmPqW0G0KNk%2B8BQ%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/1/fcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--1--fcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=b/q0wRkyUfdkOnxhedZ3AfEVV6dNBIqWJmDKJ2iMYXw%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/2/fcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--2--fcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=3jTlj3zehVAkr4iPg7c9kzUhD6VTNioPws0tmNlvWmg%3D&se=2019-06-06T02%3A23%3A16Z"
  ],
  "dcameras": [
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/0/dcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--0--dcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=L4Apvh4NZbzz8FEE2sHC0Y6ShUiKRR99jsmBUuGOC4c%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/1/dcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--1--dcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=03ayVwQ0VBIj9cfgOwj892GK2IZFq9U/HH%2BltEF9gB0%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/2/dcamera.hevc?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--2--dcamera.hevc&sr=b&sp=r&sv=2018-03-28&sig=r9Df0Yt72IFNNXU8FT85gkkXebw%2Bv2uOc0DXvyuu%2B%2B4%3D&se=2019-06-06T02%3A23%3A16Z"
  ],
  "logs": [
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/0/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--0--rlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=Yxe2QiC88aoNRwxHQsVuunRWa6MaJDIZitktOY43PfA%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/1/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--1--rlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=xRGalraKsT9PWjtyL2SCr7IqnzvxVwm0ihgvha1iNLk%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/2/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--2--rlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=60%2BJSFBn8vveU0nc3Sld1iUIiAiJBRa6PBhFl4deWWg%3D&se=2019-06-06T02%3A23%3A16Z"
  ],
  "qlogs": [
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/0/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--0--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=Yxe2QiC88aoNRwxHQsVuunRWa6MaJDIZitktOY43PfA%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/1/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--1--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=xRGalraKsT9PWjtyL2SCr7IqnzvxVwm0ihgvha1iNLk%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/2/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--2--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=60%2BJSFBn8vveU0nc3Sld1iUIiAiJBRa6PBhFl4deWWg%3D&se=2019-06-06T02%3A23%3A16Z"
  ],
  "qcameras": []
}

Response "cameras": Array of signed URLs to fcamera.hevc "dcameras": Array of signed URLs to dcamera.hevc "logs": Array of signed URLs to rlog.bz2 "qlogs": Array of signed URLs to qlog.bz2 "qcameras": Array of signed URLs to qcamera.ts

URLs are valid for 1 hour. All arrays are sorted by segment number ascending.

Qlogs

GET /v1/route/:route_name/files/qlog

Retrieve uploaded qlogs for a route.

curl https://api.commadotai.com/v1/route/99c94dc769b5d96e\|2019-05-17--17-31-58/files/qlog \
-H 'Authorization: JWT {{token}}'

Response





[
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/0/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--0--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=Yxe2QiC88aoNRwxHQsVuunRWa6MaJDIZitktOY43PfA%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/1/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--1--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=xRGalraKsT9PWjtyL2SCr7IqnzvxVwm0ihgvha1iNLk%3D&se=2019-06-06T02%3A23%3A16Z",
    "https://commadata2.blob.core.windows.net/commadata2/99c94dc769b5d96e/2019-05-17--17-31-58/2/rlog.bz2?rscd=attachment%3B%20filename%3D99c94dc769b5d96e_2019-05-17--17-31-58--2--qlog.bz2&sr=b&sp=r&sv=2018-03-28&sig=60%2BJSFBn8vveU0nc3Sld1iUIiAiJBRa6PBhFl4deWWg%3D&se=2019-06-06T02%3A23%3A16Z"
]

Response Array of signed URLs to qlog.bz2, sorted by segment number.

URLs are valid for 1 hour.

Video Stream

Base URL: https://video.comma.ai

Rear Camera Stream

GET /hls/:dongle_id/:route_signature/index.m3u8

Returns rear camera HLS stream index of MPEG-TS fragments

route_signature is the 3rd from last path component of a url from the segments endpoint.

curl https://video.comma.ai/hls/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47/index.m3u8

Response

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD

#EXTINF:3.049958,
8_61.ts?v=2
#EXTINF:3.049955,
69_61.ts?v=2
#EXTINF:3.049955,
130_61.ts?v=2
#EXTINF:3.049958,
191_61.ts?v=2
#EXTINF:3.049970,
252_61.ts?v=2
#EXTINF:3.049955,
313_61.ts?v=2
#EXTINF:3.050007,
374_61.ts?v=2
#EXTINF:3.049913,
435_61.ts?v=2
#EXTINF:3.049942,
496_61.ts?v=2
#EXTINF:3.049964,
557_61.ts?v=2
#EXTINF:3.049955,
618_61.ts?v=2

Front Camera Stream

GET /hls/:dongle_id/:route_signature/dcamera/index.m3u8

Returns front camera HLS stream index of MPEG-TS fragments

route_signature is the 3rd from last path component of a url from the segments endpoint.

curl https://video.comma.ai/hls/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47/dcamera/index.m3u8

Response

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD

#EXTINF:3.049958,
8_61.ts?v=2
#EXTINF:3.049955,
69_61.ts?v=2
#EXTINF:3.049955,
130_61.ts?v=2
#EXTINF:3.049958,
191_61.ts?v=2
#EXTINF:3.049970,
252_61.ts?v=2
#EXTINF:3.049955,
313_61.ts?v=2
#EXTINF:3.050007,
374_61.ts?v=2
#EXTINF:3.049913,
435_61.ts?v=2
#EXTINF:3.049942,
496_61.ts?v=2
#EXTINF:3.049964,
557_61.ts?v=2
#EXTINF:3.049955,
618_61.ts?v=2

Derived Data

GPS Path

After openpilot uploads a log, a JSON array of GPS coordinates interpolated at 1hz is exposed at a signed URL in the cloud. As segments are uploaded, route.coords will be appended to atomically.

To access the GPS path, first obtain a segment url key from the /v1/devices/:dongle_id/segments response. Chop off the last path component, which represents the segment number. Append route.coords. For example:

https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47/route.coords

Video Frames (every 5s)

JPEGs are extracted every 5s from road camera video and are exposed at a signed URL in the cloud.

To access the JPEGs, first obtain a segment url key from the /v1/devices/:dongle_id/segments response. Chop off the last path component, which represents the segment number. Append secN.jpg where N is the 0-indexed number of seconds since start of the route. For example:

https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47/sec400.jpg

openpilot

openpilot auth

POST https://api.commadotai.com/v2/pilotauth/

Query parameters

imei: Device IMEI

imei2: Device IMEI, second slot

serial: Device Serial

public_key: 2048-bit RSA Public Key

register_token: JWT token signed by your private key containing payload: {"register": True}

curl -X POST 'https://api.commadotai.com/v2/pilotauth/?imei=000000000000000&imei2=000000000000001&serial=aaaaaaaa&public_key=ssh-rsa%20AAAAB3NzaC1yc2EAAAADAQABAAABAQDeEAshPfzEDsSg8yZnidU8%2BGZSw%2BjS21vcoDlnrnI/3SQ8njvY0o6hHIt9Soxf%2BvnNF9amZ51tysblNIhkF9igwqXKNaEzIX2MKJSwp0rNdJSoLM8SSYBNlfyFUTsoakW2p6FQ9E01RgspFR8xBT91lrJ6eKKKmYP/P24mF6KfgdZ57%2BvTehmrj5MJi14lN18q8KM8nyppNvB5t0ijMeBq64x0TZig3o7rQxzzX0uMemNWZ3fXADL7lJUcyNO8Vv70%2BAddP9Ek8zgna7msUbzwbV1O1eUb9t3jlKHTN7zhfTXrxzwoNETHMn0569rZFmqfUf%2BHBEKLgUck1QMZIkRX%20root%40localhost&register_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWdpc3RlciI6dHJ1ZSwiZXhwIjoxNTU5ODUzNTA3fQ.h5RMQ4ThPDy3Otadq0pcmnTROdXDklfxj6ItLqzxc8sNzioMa9qBeBRA22H75N11ucAOwxaF6ckO5AGDcDf5VwMwGbdibaVnTfUHP4mofz6usD-92lJbzQ1k0YwebPftBAoL4epRfS52Z1JVVLxNwCW9Mb9rexnc_tn2S7JQzHJUb1BLGSGengC1MtReXvIIjDK9FP-KAI9ZluvzIXnNtGvVfzJiVPwMQzmY4xRUewVXUJPPs6tv1oz26UW4Kd9aYhQo4KJAIUTAvY0gA_SYrcZIzC1pFcHY50Qot2HqW4HdJcoaXWqaWakbz4xUpswbiaQi1bdZoVa8b5Ht9r8p_g'

Response

{
  "dongle_id": "02c45f73a2e5c6e9",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImZvbyIsImlhdCI6MTU2MDc1NDUzMywibmJmIjoxNTYwNzU0NTMzLCJleHAiOjE1OTIyOTA1MzN9.V34lp0Nq0EZMw7b5I8xnZaMvIbS2eisUsrFbXg4itaY"
}

Response

Key Type Description
"dongle_id" (string) Dongle ID
"access_token" (string) JWT token (see Authentication)

Athena WebSocket

Listen for inbound JSON-RPC requests. This is used by openpilot's athenad.py.

Base URL: wss://athena.comma.ai:8765

/:dongle_id

curl --include \
     --no-buffer \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: athena.comma.ai:8765" \
     --header "Origin: https://athena.comma.ai:8765" \
     --cookie "jwt={{device_token}}" \
     https://athena.comma.ai:8765/02c45f73a2e5c6e9

Upload URL

Request a URL to which an openpilot file can be uploaded via PUT request. This endpoint only accepts tokens signed with a device private key (openpilot 0.6.3 and newer.)

V 1.3

GET /v1.3/:dongle_id/upload_url/

Parameters

Key Description
path segment directory and name of file to upload from openpilot data directory. for example, 2019-06-06--11-30-31--9/fcamera.hevc
curl https://api.commadotai.com/v1.3/ccfab3437bea5257/upload_url/?path=2019-06-06--11-30-31--9/fcamera.hevc \
-H 'Authorization: JWT jwt_signed_with_device_private_key'

Response

{
  "url": "https://commaincoming.blob.core.windows.net/commaincoming/239e82a1d3c855f2/2019-06-06--11-30-31/9/fcamera.hevc?sr=b&sp=cw&sig=cMCrZt5fje7SDXlKcOIjHgA0wEVAol71FL6ac08Q2Iw%3D&sv=2018-03-28&se=2019-06-13T18%3A43%3A01Z"
}

Response

Key Type Description
"url" (string) URL to which a PUT request can be sent with file contents

V 1.4

GET /v1.4/:dongle_id/upload_url/

Parameters

Key Description
path segment directory and name of file to upload from openpilot data directory. for example, 2019-06-06--11-30-31--9/fcamera.hevc
expiry_days number of days the url should be valid. Valid values beteen 1 and 30. Optional, default is 1 day.
curl https://api.commadotai.com/v1.4/ccfab3437bea5257/upload_url/?path=2019-06-06--11-30-31--9/fcamera.hevc&expiry_days=1 \
-H 'Authorization: JWT jwt_signed_with_device_private_key'

Response

{
  "url": "https://commaincoming.blob.core.windows.net/commaincoming/239e82a1d3c855f2/2019-06-06--11-30-31/9/fcamera.hevc?sr=b&sp=c&sig=cMCrZt5fje7SDXlKcOIjHgA0wEVAol71FL6ac08Q2Iw%3D&sv=2018-03-28&se=2019-06-13T18%3A43%3A01Z"
}

Response

Key Type Description
"url" (string) URL to which a PUT request can be sent with file contents

Athena

Athena HTTP

Send JSON-RPC requests to the active websocket client for a given device identified by Dongle ID.

Base URL: https://athena.comma.ai

POST /:dongle_id



Request body

{
  "method": "getMessage",
  "params": {"service": "deviceState", "timeout": 5000},
  "jsonrpc": "2.0",
  "id": 0
}

JSON-RPC payload with keys:

Key Type Description
"method" (string) json-rpc method - see openpilot athenad.py for supported methods
"params" (object) method-specific params. For getMessage:
"params.service" (string) service name (see openpilot service_list.yaml)
"params.timeout" (integer) milliseconds client should wait for message from service
"jsonrpc" (string) constant, "2.0"
"id" (integer) constant, 0





curl https://athena.comma.ai/02c45f73a2e5c6e9 \
-d '{"method":"getMessage","params":{"service":"deviceState","timeout":5000},"jsonrpc":"2.0","id":0}' \
-H 'Authorization: JWT {{token}}'

Response

{
  "jsonrpc": "2.0",
  "result": {
    "deviceState": {
      "batteryStatus": "Discharging",
      "freeSpace": 0.9546145796775818,
      "bat": 28700,
      "usbOnline": false,
      "batteryCurrent": 330808,
      "startedTs": 0,
      "mem": 333,
      "chargingError": false,
      "cpu2": 333,
      "cpu3": 333,
      "cpu0": 343,
      "cpu1": 323,
      "fanSpeed": 0,
      "batteryVoltage": 4200414,
      "chargingDisabled": false,
      "started": false,
      "batteryPercent": 93,
      "gpu": 309,
      "thermalStatus": "green"
    },
    "valid": true,
    "logMonoTime": 107226885676532
  },
  "id": "ba0daa7a-a208-410f-8f11-1e1e6f29edeb"
}

Response

JSON-RPC response object with keys:

Key Type Description
"jsonrpc" string "2.0", constant
"result" object method-specific result. For getMessage, it's a zmq message encoded as dictionary. see openpilot log.capnp
"id" string request ID

Leaderboard

List top leaders

GET /v2/leaderboard/

Returns overall and last-week comma point leaders.

curl https://api.commadotai.com/v2/leaderboard/ \
-H 'Authorization: JWT {{token}}'
{
  "all": [
    {
      "joinDate": "2016-04-11",
      "points": 49673,
      "username": "lordricky",
      "weekly": 2338
    },
    {
      "joinDate": "2016-03-25",
      "points": 2291,
      "username": "tom",
      "weekly": 0
    },
    ...
  ],
  "weekly": [
    {
      "joinDate": "2016-04-11",
      "points": 49673,
      "username": "lordricky",
      "weekly": 2338
    },
    {
      "joinDate": "2016-03-25",
      "points": 2291,
      "username": "tom",
      "weekly": 0
    },
    ...
  ]
}




Response

JSON object with keys:

Key Type Description
"all" (array) Leaderboard entry objects sorted by points key. Structure of each:
"joinDate" (string) Join date formatted as ISO8601 string
"points" (integer) All-time comma points total
"username" (string) Username
"weekly" (integer) comma points earned in last 7 days
"weekly" (array) Same structure as all, but sorted by weekly points.

Billing

Subscription Status

GET /v1/prime/subscription

Retrieve subscription status for a device

curl https://billing.comma.ai/v1/prime/subscription?dongle_id=b0c9d2329ad1606b \
-H 'Authorization: JWT {{token}}'

Query Parameters

dongle_id required

The dongle ID of the device

Response

{
  "amount": 2400,
  "is_prime_sim": true,
  "next_charge_at": 1595720380,
  "sim_id": "0000000000000000000",
  "subscribed_at": 1587944381,
  "trial_claim_end": null,
  "trial_claimable": false,
  "trial_end": 1595720380,
  "user_id": "google_104654435692089730759"
}




Response

JSON object with keys:

Key Type Description
"amount" (integer) Monthly subscription cost, in USD cents
"is_prime_sim" (bool) True if subscription includes data plan
"next_charge_at" (integer) Unix timestamp of next scheduled subscription charge
"sim_id" (string, nullable) 19-digit SIM ID, non-null if subscription includes data plan
"subscribed_at" (integer) Unix timestamp of subscription start time
"trial_claim_end" (integer, nullable) Unix timestamp of deadline to claim trial, if eligible
"trial_claimable" (bool) True if eligible for trial and before
"trial_end" (integer) Unix timestamp of trial end
"user_id" (string) OAuth user ID of subscription customer

Activate Subscription

POST /v1/prime/pay

Activate subscription for a device, optionally with a compatible SIM card.

curl https://billing.comma.ai/v1/prime/pay \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"dongle_id": "b0c9d2329ad1606b", "sim_id": "0000000000000000000", "stripe_token": "stripe_token"}'

Request Body

JSON object with keys:

Key Type Description
"dongle_id" (string) Device dongle ID
"sim_id" (string, nullable) 19-digit SIM ID to be associated with subscription data plan. Null if subscription does not include data plan.
"stripe_token" (string) Card token from Stripe client API (https://stripe.com/docs/api/tokens)

Responses

{"success": 1}
{"error": "Subscription already active"}





Response

JSON object with keys:

Key Type Description
"success" integer 1 if subscription activated
"error" string (optional) Error description

Get Payment Source

GET /v1/prime/payment_source

Get current payment source

curl https://billing.comma.ai/v1/prime/payment_source \
-H 'Authorization: JWT {{token}}'
{
  "brand": "Visa",
  "country": "US",
  "exp_month": 12,
  "exp_year": 2026,
  "last4": "4242",
  "tokenization_method": "apple_pay"
}




Response

JSON object with keys:

Key Type Description
"brand" (string) Card brand
"country" (string) Card country
"exp_month" (integer) Card expiration month
"exp_year" (integer) Card expiration year
"last4" (string) Last four digits of card number
"tokenization_method" (string, nullable) One of ("apple_pay", "android_pay", null)

Set Payment Source

POST /v1/prime/payment_source

Update payment source associated with an account. Stripe securely stores all card information.

curl https://billing.comma.ai/v1/prime/payment_source \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"stripe_token": "some_stripe_token"}'

Request Body

JSON object with keys:

Key Type Description
"stripe_token" (string) Card token from Stripe client API (https://stripe.com/docs/api/tokens)

Response

{
  "brand": "Visa",
  "country": "US",
  "exp_month": 12,
  "exp_year": 2026,
  "last4": "4243",
  "tokenization_method": null
}




Response

JSON object with keys:

Key Type Description
"brand" (string) Card brand
"country" (string) Card country
"exp_month" (integer) Card expiration month
"exp_year" (integer) Card expiration year
"last4" (string) Last four digits of card number
"tokenization_method" (string, nullable) Non-null if payment source is tokenized using a mobile payment provider ("apple_pay", "android_pay"). Otherwise, null if card is used directly.

Cancel Subscription

POST /v1/prime/cancel

Cancel subscription for device

curl https://billing.comma.ai/v1/prime/cancel \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"dongle_id": "b0c9d2329ad1606b"}'

Request Body

JSON object with keys:

Key Type Description
"dongle_id" (string) Device dongle ID associated with subscription to be cancelled
{"success": 1}

Navigation

Set destination

POST /v1/navigation/:dongle_id/set_destination

Set navigation destination on device. If device is offline, the destination will be saved in the database to be retrieved when the device boots. Also updates navigation recents list.

curl -X POST https://api.commadotai.com/v1/navigation/0375fdf7b1ce594d/set_destination \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"place_name": "San Diego Airport", "place_details": "3225 N Harbor Dr, San Diego, CA 92101, United States", "latitude": 32.7304, "longitude": -117.195}'

Request body

JSON object

Key Type Description
"place_name" (string) Short name of destination
"place_details" (string) Address details of destination, should not include short name
"latitude" (float) Latitude, degrees
"longitude" (float) Longitude, degrees

Response

JSON object with keys:

Key Type Description
"success" (bool) Whether the destination is successfully set
"saved_next" (bool) True if device was offline and destination is set to be retrieved on device startup
"error" (string, optional) Error description

Retrieve next destination

GET /v1/navigation/:dongle_id/next

Retrieve next location from database, this was set on Set destination if the device was offline. Next location is removed from database after this call and when a new destination is set.

curl https://api.commadotai.com/v1/navigation/0375fdf7b1ce594d/next \
-H 'Authorization: JWT {{token}}'

Query parameters

None

Response

null if no destination is set, or JSON object:

Key Type Description
"place_name" (string) Short name of destination
"place_details" (string) Address details of destination, should not include short name
"latitude" (float) Latitude, degrees
"longitude" (float) Longitude, degrees

Retrieve saved locations

GET /v1/navigation/:dongle_id/locations

Retrieve saved locations from database.

curl https://api.commadotai.com/v1/navigation/0375fdf7b1ce594d/locations \
-H 'Authorization: JWT {{token}}'

Query parameters

None

Response

JSON array filled with objects (ordered by modfied):

Key Type Description
"id" (int) identifier of this saved location
"dongle_id" (string) dongle_id of device
"place_name" (string) Short name of destination
"place_details" (string) Address details of destination, should not include short name
"latitude" (float) Latitude, degrees
"longitude" (float) Longitude, degrees
"save_type" (string) enum of favorite, recent
"label" (string, optional) optional label for locations with save_type: favorite
"modified" (string) when this saved location was last modified, useful for when save_type: recent

Set saved locations

PUT /v1/navigation/:dongle_id/locations

Save new location in database.

curl -X PUT https://api.commadotai.com/v1/navigation/0375fdf7b1ce594d/locations \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"place_name": "San Diego Airport", "place_details": "3225 N Harbor Dr, San Diego, CA 92101, United States", "latitude": 32.7304, "longitude": -117.195, "save_type": "favorite", "label": "work"}'

Request body

JSON object:

Key Type Description
"place_name" (string) Short name of destination
"place_details" (string) Address details of destination, should not include short name
"latitude" (float) Latitude, degrees
"longitude" (float) Longitude, degrees
"save_type" (string) enum of favorite, recent, next
"label" (string, optional) optional label for locations with save_type: favorite

Response

{"success": true}

Update saved locations

PATCH /v1/navigation/:dongle_id/locations

DELETE /v1/navigation/:dongle_id/locations

Update or delete existing saved location in database.

curl -X PATCH https://api.commadotai.com/v1/navigation/0375fdf7b1ce594d/locations \
-H 'Authorization: JWT {{token}}' \
-H 'Content-Type: application/json' \
-d '{"id": 42, "save_type": "favorite", "label": "work"}'

Request body

JSON object:

Key Type Description
"id" (int) identifier of saved location
"save_type" (string, optional) enum of favorite, recent, next
"label" (string, optional) optional label for locations with save_type: favorite

Response

{"success": true}