SimpleOTA¶
SimpleOTA is a firmware over-the-air (FOTA) platform for ESP32 devices, designed to be operationally boring and developer-friendly.
- Deterministic canary rollouts: same device, same seed, same cohort. Always.
- Pre-signed downloads: firmware bytes never traverse the application tier. Devices download directly from object storage with short-lived URLs.
- Arduino + ESP-IDF: both frameworks are first-class. First-party Arduino client: SimpleOTAClient. ESP-IDF client coming next.
- Project-scoped build numbers: strictly monotonic, never reused.
- Hardware-safe responses: devices receive 200 + JSON status for business outcomes (no update, over-limit, inactive). Real HTTP errors are reserved for genuine infrastructure failures so a fleet can't retry-storm you.
Where to start¶
-
New here?
Walk through signup, your first project, and your first OTA delivery.
-
Concepts
The mental model: projects, devices, channels, deployments, build numbers, cohorts.
-
Guides
Practical end-to-end recipes for Arduino, ESP-IDF, and CI/CD.
-
API
Device API and developer API reference.
Browse all documentation¶
Getting started
Sign up · First project · First device · First deployment
Concepts
Projects · Devices · Device groups · Release channels · Firmware artifacts · Build numbers · Deployments · Cohorts and rollout math · Compatibility · Security modes
Dashboard
Projects · Devices · Artifacts · Deployments · Tokens · Billing
Firmware integration
Arduino · ESP-IDF · Manifest schema · Device tokens
CI/CD
GitHub Actions · GitLab CI
Deployment management
Promoting deployments · Pausing deployments · Trial install and rollback
API reference
Authentication · Device API · Developer API · Errors
Billing
Plans and limits · Subscribing · FAQ
What does the device flow look like?¶
sequenceDiagram
participant Dev as ESP32 device
participant API as SimpleOTA
participant S3 as Object storage
Dev->>API: POST /api/v1/ota/check/<br/>(token, device_id, build, hw)
API->>API: Identify / auto-register
API->>API: Find active deployments
API->>API: Filter by compatibility
API->>API: Cohort: stable_hash(seed, device)
alt newer build assigned
API-->>Dev: 200 { update_available: true, url, build_number, checksum }
Dev->>S3: GET pre-signed URL
S3-->>Dev: firmware.bin
Note over Dev: flash, validate, reboot
Dev->>API: POST /api/v1/ota/status/<br/>(success / failed / rolled_back)
else nothing assigned
API-->>Dev: 200 { update: false }
end
See Compatibility and Cohorts and rollout math for the full ordering and edge cases. For the post-flash trial install and rollback lifecycle, see Rollback.