Manifest schema¶
The manifest is a JSON sidecar uploaded alongside the firmware binary. It declares what hardware the binary supports.
- Required for Arduino artifacts. The Arduino binary is unreliable for self-description.
- Optional for ESP-IDF artifacts.
Schema¶
{
"framework": "arduino | esp_idf",
"version_label": "1.4.2",
"chip_family": "esp32 | esp32s2 | esp32s3 | esp32c3 | esp32c6 | esp32h2",
"board_id": "free-form string, must match device's board_id",
"hardware_revision_min": "rev-a",
"hardware_revision_max": "rev-c",
"partition_profile": "free-form string, e.g. default_4mb, ota_8mb",
"nvs_schema_version": 1,
"security_mode": "basic | token | signed",
"signing_metadata": {},
"release_notes": "Optional description, max 4096 chars.",
"compatibility": { "any_custom_key": "any_value" }
}
Required fields¶
| Field | Constraints |
|---|---|
framework |
One of arduino, esp_idf. Must match device's framework. |
version |
Non-empty string, max 64 chars. Human-readable version label. |
chip_family |
Non-empty string, max 32 chars. Must match device's chip_family. |
Optional fields¶
| Field | Behavior |
|---|---|
board_id |
If set, device's board_id must match exactly. |
hardware_revision_min |
Inclusive lower bound on the device's hardware_revision. Empty = no lower bound. |
hardware_revision_max |
Inclusive upper bound on the device's hardware_revision. Empty = no upper bound. |
partition_profile |
Stored on the artifact; advisory; not enforced by the engine today. |
nvs_schema_version |
Stored on the artifact; advisory; not enforced by the engine today. |
security_mode |
One of basic, token, signed. token requires per-device tokens at check time; signed requires a valid signing_metadata. |
signing_metadata |
Required for (and only valid with) security_mode: "signed": {"key_id", "algorithm", "signature"}. Verified server-side at upload. See below. |
release_notes |
Plain-text change description. Max 4096 chars. |
compatibility |
Free-form JSON object; extra constraints for future engine use. |
Validation¶
Manifests are validated against a strict schema at upload time. A malformed manifest fails the upload with a descriptive error rather than silently storing a broken artifact.
Signed uploads¶
For security_mode: "signed", signing_metadata is mandatory and is
cryptographically verified against the project's registered public key
before the artifact is accepted:
{
"framework": "arduino",
"version_label": "2.1.0",
"chip_family": "esp32",
"security_mode": "signed",
"signing_metadata": {
"key_id": "prod-2026",
"algorithm": "ed25519",
"signature": "<base64 Ed25519 signature over the raw binary bytes>"
}
}
The signature must cover the exact binary bytes being uploaded. Uploads
with an invalid signature, unknown key_id, or revoked key are rejected.
Providing signing_metadata with any other security_mode is a
validation error. Full walkthrough: signed firmware guide.
Example: GitHub Actions¶
The upload step from the GitHub Actions guide builds a manifest and uploads in one step:
MANIFEST_JSON=$(cat <<EOF
{
"framework": "arduino",
"version_label": "1.4.2",
"chip_family": "esp32",
"board_id": "esp32dev",
"partition_profile": "default_4mb",
"nvs_schema_version": 1,
"security_mode": "basic"
}
EOF
)
curl -X POST "${SIMPLEOTA_BASE_URL}/api/v1/projects/${SIMPLEOTA_PROJECT_ID}/artifacts/" \
-H "Authorization: Bearer ${SIMPLEOTA_TOKEN}" \
-F "manifest=${MANIFEST_JSON}" \
-F "[email protected]"