Device tokens¶
A device token is a per-device credential that lets a single ESP32 authenticate directly with the OTA check endpoint, without using a project token that could auto-register new devices.
When to use a device token¶
| Situation | Recommended token |
|---|---|
| Development, CI, or first device registration | Project API token |
| Established production fleet | Device token |
A project token with device scope can auto-register devices up to your plan limit. Once a device is registered and deployed to production, issuing it a dedicated device token removes the risk of a compromised project token being used to register rogue devices or pull updates on behalf of another device.
A device token:
- authenticates at
/api/v1/ota/check/and/api/v1/ota/status/ - cannot auto-register new devices
- cannot access the developer API
- is scoped to exactly one device
Token format¶
Device tokens carry a soto_dev_ prefix to distinguish them from
project tokens (soto_proj_) and personal API tokens (soto_pat_) in
logs and audit trails.
SimpleOTA stores only a SHA-256 hash of the full token and the first 16 characters as a prefix for audit and debugging purposes. The raw token is shown once at creation time and cannot be recovered; treat it like a password.
Provisioning a device token¶
There are two flows depending on whether the device has already registered itself.
Flow A: a device that already checked in¶
For devices that first booted using a project token and auto-registered, switch them to per-device authentication from the dashboard.
- Open the dashboard and navigate to the project.
- Click into the device row from the Devices list.
- On the device detail page, in the Authentication section, click Issue token (or Rotate token if one already exists).
- Copy the raw token from the yellow alert box immediately; it is shown once and cannot be retrieved again.
- Flash the device with the new token in place of the project token.
Flow B: factory provisioning a new device¶
For devices that have not yet booted, you can pre-create the device row and its token so the firmware can ship pre-flashed with credentials.
- Open the dashboard and navigate to the project.
- In the Devices card, click Add device.
- Enter the device's stable
device_id(MAC address, chip ID, serial, or NVS UUID). Do not enter hardware metadata: the device will self-report its chip family, board, framework, hardware revision, and partition profile on its first check-in. - Submit the form. A new device row is created and a token is issued immediately. Copy the raw token from the yellow alert box.
- Flash the device with the token. On its first OTA check-in, the metadata fields populate automatically.
Via the developer API¶
The same flows are available as REST endpoints under your personal
API token (soto_pat_*) or a project API token with the api scope.
# Create a device and issue its token in one step (factory provisioning).
curl -X POST https://simpleota.com/api/v1/projects/<project_id>/devices/ \
-H "Authorization: Bearer soto_pat_..." \
-H "Content-Type: application/json" \
-d '{"device_id": "esp32-sensor-0001"}'
# 201 → returns full device representation plus `raw_token`.
# Issue or rotate the token on an existing device.
curl -X POST https://simpleota.com/api/v1/projects/<project_id>/devices/<device_id>/token/ \
-H "Authorization: Bearer soto_pat_..."
# 200 → returns {device_id, key_prefix, raw}.
# Revoke the token (device falls back to project-token auth).
curl -X DELETE https://simpleota.com/api/v1/projects/<project_id>/devices/<device_id>/token/ \
-H "Authorization: Bearer soto_pat_..."
# 204 → no content.
These endpoints make it trivial to script bulk provisioning: loop over
your device IDs and store each raw_token in your build pipeline's
secrets manager keyed by device_id.
Using a device token in firmware¶
The Authorization header is identical to a project token; no other
code change is required:
If a device was previously using a project token, switching to a device token is a header-only change. The request body, endpoint URL, and response format are all identical.
Arduino example¶
If you're using the
SimpleOTAClient library, just pass the device token as the
project-token argument; everything else is the same. The raw
HTTPClient form looks like this:
HTTPClient http;
http.begin("https://simpleota.com/api/v1/ota/check/");
http.addHeader("Authorization", "Bearer soto_dev_your_random_secret_here");
http.addHeader("Content-Type", "application/json");
String body = "{\"device_id\":\"" + String(DEVICE_ID) +
"\",\"current_build_number\":" + String(currentBuild) + "}";
int code = http.POST(body);
Security properties¶
| Property | Detail |
|---|---|
| Storage | SHA-256 hash only; raw token never persisted |
| Audit | First 16 characters stored as prefix for log correlation |
| Scope | Single device; cannot register or access other resources |
| Revocation | Instant; no caching between request and hash check |
| Logging | Prefix only logged, not the full token |
| Last-used tracking | device_token_last_used_at updated on every successful auth |
Rotating a device token¶
In the dashboard, click Rotate token on the device detail page. The new token replaces the old one immediately (hard cutover): the previous raw token stops authenticating the moment the rotation completes. Flash the new token before reboot, or the device will fall back to its project-token auth (if any).
Revoking a device token¶
In the dashboard, click Revoke next to the token in the
Authentication section of the device detail page. Revocation is
instant; the device will fall back to project-token auth (if it still
holds a valid project token) or receive 401 Unauthorized on its next
check-in.
Related¶
- Security modes: the
tokensecurity mode requires a device token at check-in time. - Authentication: full token acceptance matrix and error codes.