Skip to content

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]"