install_certificate
ReferenceAudience: API consumerUse: install a certificate or key into the reader's trust store
Overview
install_certificate installs a certificate (or key) into the reader's trust store — for MQTT-TLS brokers, Wi-Fi Enterprise (EAP), the file store, or client/server auth. Content is supplied one of two ways, chosen by certDetails.certSource:
HTTP(default) — the device downloads each component from the URLs inurl[].DIRECT— you provide the content inline incertificateBundle.
It is a state-changing command on the device-management (MGMT) endpoint. Installed certificates are then referenced by name from config_endpoint (MQTT_TLS) and set_wifi (Enterprise).
install_certificate is asynchronous: the reply code 1 is an accept, not an install confirmation. Verify with get_installed_certificates (and, for HTTP, the FILE_DOWNLOAD alerts). Do not gate success on code == 0. See Lifecycle.
Details
| Property | Value |
|---|---|
| Interaction Pattern | Asynchronous Request / Accept (device acks with code 1; completion verified out-of-band) |
| State Change | STATE-CHANGING (writes to the trust store; asynchronous) |
| Reversibility | REVERSIBLE (remove with delete_certificate) |
| Required Request Fields | command, requestId, certDetails (with type and authenticationType) |
| Applies To | Endpoint: Management (MGMT). Reader: RFD40 series, RFD90 series |
| API Version | V1.21 (API Version Reporting) |
| Related | get_installed_certificates, delete_certificate, config_endpoint, set_wifi |
When to Use
Use install_certificate to provision the certificates other commands depend on:
- Before
MQTT_TLS— install theca_cert/client_cert/client_key(typemqtt) thatconfig_endpointreferences insecurityParams. - Before Wi-Fi Enterprise — install
wifi-type certificates thatset_wifireferences in itscertificatearray. - File-store trust — install a
filestoreCA used to authenticate HTTPS downloads. - Choose the source: use
DIRECTwhen you can embed the content (no network dependency); useHTTPwhen the device can reach your file server (watch theFILE_DOWNLOADalerts).
Topic Mapping
| Message | Direction | Topic | Note |
|---|---|---|---|
| Request | App → Reader | <tenantId>/MGMT/clients/cmnd/<serial> | On the management endpoint. |
| Response | Reader → App | <tenantId>/MGMT/clients/resp/<serial> | The code 1 accept. Correlated by the in-payload requestId. |
| Event | Reader → App | <tenantId>/MGMT/clients/event/<serial> | For HTTP installs, the device emits asynchronous FILE_DOWNLOAD alerts (per-file download/save) here. See alerts. |
Topics follow the pattern <tenantId>/<topic>/<serial> — the tenant id assigned to you at provisioning (a slot you fill in, never a literal), the base topic you configure on the endpoint, and the reader's serial number, which the reader appends itself in its model-prefixed form (for example RFD40-212735201D0053). App → Reader means your app publishes and the reader subscribes; Reader → App means the reader publishes and your app subscribes.
See Topics and Channels.
Key Fields
certDetails.certSource(request) —HTTP(useurl) orDIRECT(usecertificateBundle).certDetails.type(request) — the certificate category (mqtt,wifi,filestore, …); scopes where the certificate can be used.certDetails.name(request) — the logical name you choose for the entry. It is optional at install time, butnametogether withtypeis what identifies an installed certificate afterward:delete_certificatetakes exactly that pair, and a delete that omitsnameremoves every installed certificate of the matchingtype.certDetails.authenticationType(request) —NONEorCERTIFICATE(certificate-authenticated download).certificateBundle.client_key/cert_key_password(request) — ⚠️ secrets you send inline (DIRECT); mask them. InHTTPmode aurlentry withkey: cert_key_passwordlikewise carries a plaintext password in itsvalue. See the credential warning below.response.code(response) —1means accepted, not installed; confirm withget_installed_certificates. See Response Codes.
Request Payload
The envelope is command, requestId, and the certDetails payload. Pick a certificate scenario below; the Example and Schema update together. Use the Schema tab for the full field reference and the Example tab for the concrete payload.
In DIRECT mode certificateBundle.client_key (private key) and cert_key_password (password) are secrets in the request — mask them as ********. In HTTP mode, a url entry with key: cert_key_password also carries a plaintext password in its value — treat it the same way. Send install_certificate only over secured channels. The device never echoes them, and the read-back never exposes private-key material.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | install_certificate | Fixed command name. |
requestId* | string | — | abc123 | A unique identifier for the request; echoed back in the response. |
certDetails* | object | — | — | The certificate to install. Required by the contract, which also requires type and authenticationType within it. |
name, nesting level 2 | string | — | exampleAgent | Logical name for the entry. Installed entries are named {name}_{component} (e.g. testMqttCert_ca_cert). |
type*, nesting level 2 | enum | clientservermqttwififilestore | client | Certificate category — where the certificate is used. Required (see the not-enforced note in Request Semantics). |
authenticationType*, nesting level 2 | enum | NONECERTIFICATE | CERTIFICATE | Authentication used to reach the remote download source. NONE = no auth; CERTIFICATE = certificate-authenticated download. |
certSource, nesting level 2 | enum | HTTPDIRECT | HTTP | How content is supplied. Optional; defaults to HTTP. HTTP = download from url; DIRECT = inline certificateBundle. |
certFormat, nesting level 2 | enum | PEMBASE64 | BASE64 | Encoding of the certificate material, inline or downloaded. Optional; the contract states no default. BASE64 is PEM text base64-encoded again, not a bare DER body. |
url, nesting level 2 | array | — | — | HTTP mode — a list of {key, value} entries mapping each certificate component to its download URL. Required for HTTP (the default when certSource is omitted); missing → code 29. |
key, nesting level 3 | enum | ca_certclient_keyclient_certcert_key_password | ca_cert | The certificate component to download. |
value, nesting level 3 | string | — | https://192.168.0.104:8443/mqtt_ca_cert.pem | Download URL for the component. For cert_key_password, this is the key password value (a secret — mask it). |
verificationType, nesting level 2 | enum | VERIFY_NONEVERIFY_HOST_AND_PEER | VERIFY_NONE | TLS verification mode applied when validating the remote download endpoint (the HTTP(S) certificate source), not when the installed certificate is later used. Use VERIFY_HOST_AND_PEER for an HTTPS source; VERIFY_NONE must not be used in production. |
certificateBundle, nesting level 2 | object | — | — | DIRECT mode — inline certificate content. Required for DIRECT; missing → code 30. Supply content for one certificate type. |
ca_cert, nesting level 3 | string | — | -----BEGIN CERTIFICATE-----… | Inline CA certificate (PEM). Public — not a secret. |
client_key, nesting level 3 | string | — | LS0tLS1CRUdJTiBSU0Eg… | Inline client private key (PEM, PKCS1) — a secret; mask it. |
client_cert, nesting level 3 | string | — | LS0tLS1CRUdJTiBDRVJU… | Inline client certificate (PEM). Public — not a secret. |
cert_key_password, nesting level 3 | string | — | — | Password that decrypts an encrypted client private key, when required — a secret; mask it. |
caCertificateFileContent, nesting level 2 | string | — | -----BEGIN CERTIFICATE-----… | HTTP mode only — inline CA used to authenticate the HTTPS download (when authenticationType = CERTIFICATE). If empty, an already-installed filestore certificate is used. |
Request Semantics
Modes. certDetails.certSource selects how the certificate content is supplied — HTTP (download) or DIRECT (inline):
HTTP(default). Supplyurl[]with a{key, value}entry per component (ca_cert,client_cert,client_key,cert_key_password). The device downloads each; forauthenticationType: CERTIFICATEover HTTPS, supplycaCertificateFileContent(or rely on an installed filestore CA). Requires device → file-server reachability; missingurlreturns code29. The device emitsFILE_DOWNLOADalerts as it fetches.DIRECT. SupplycertificateBundlewith inline PEM content for onetype. No network dependency; missingcertificateBundlereturns code30.
Invalid enum values (e.g. type, certSource) return code 23. The contract does not forbid unrecognized fields, so a misspelled field still passes schema validation. How the reader responds to such a field is not specified in the available sources, so check field names client-side before you send.
- Choosing
type. The enum acceptsclient,server,mqtt,wifi, andfilestore. Current deployments needwifi(Enterprise EAP, referenced byset_wifi),filestore(the CA that authenticates HTTPS downloads), andmqtt(broker TLS, referenced byconfig_endpoint).clientandserverare the generic client-side and server-side categories; the schema gives them no further gloss beyond "the certificate category that identifies where the certificate is used", and its own field examples pairtype: clientwith an agent certificate (name: exampleAgent). - One install, one
type— and file-store trust must be typedfilestore.certDetails.typeis a single string with a five-member enum, not a list, andcertificateBundlesupplies certificate content "for one certificatetype", so eachinstall_certificatecall installs exactly one category. A file-store CA is therefore typedfilestoreand cannot also be typedclientorserver— send a secondinstall_certificateif you need a second category. This matters for HTTPS downloads: withauthenticationType: CERTIFICATEand an emptycaCertificateFileContent, the schema names an already-installedfilestorecertificate as the trust anchor the device falls back to, so installing the same CA underclientorserverleaves nofilestoreentry for that fallback to use. typeandauthenticationTypeare required but not firmware-enforced. The schema requires both withincertDetails, but the device accepts a payload omitting them (still returnscode 1) and installs a malformed entry (e.g.type: null). Always send both; do not rely on the device to reject their absence.- Certificate size limit — 4 KB. Certificate content is capped at 4 KB (4096 bytes) per certificate file, not per request; keep each certificate within the limit.
- PEM, or base64-encoded PEM. The device supports certificates in PEM format, or as PEM text base64-encoded again (
certFormat: BASE64) — PEM being the base64 encoding delimited by header/footer markers, e.g.-----BEGIN CERTIFICATE-----/-----END CERTIFICATE-----,-----BEGIN RSA PRIVATE KEY-----/-----END RSA PRIVATE KEY-----, and-----BEGIN ENCRYPTED PRIVATE KEY-----/-----END ENCRYPTED PRIVATE KEY-----. - PKCS1 (RSA) key encoding. The reader requires private keys in PKCS1 format — the public-key-cryptography standard for RSA.
Response Payload
The immediate reply is an accept — command, requestId, apiVersion, and response with code 1. It confirms receipt, not installation.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | install_certificate | Echoes the executed command. |
requestId* | string | — | abc123 | Echoes the request's requestId — pairs reply to request. |
apiVersion* | enum | V1.0V1.1V1.2V1.21V1.22 | V1.1 | API version reported by this command. Emitted per-handler, not device-wide. |
response* | object | — | — | Accept/status envelope. This is an asynchronous accept, not a terminal install result (see below). |
code*, nesting level 2 | integer | 0–101 | 0 | 1 = accepted (the success/accept code for this command — not 0). Non-1 = rejected. See Response Codes below. |
description*, nesting level 2 | string | — | Success | Human-readable status. |
Lifecycle
Acknowledgment
Because the accept (code 1) is not a terminal result, confirm the install actually landed. There is no terminal success/failure message on the response topic after the code 1 accept. A consumer that treats code == 0 as the success condition will misread every install_certificate reply.
Progress
For HTTP, watch FILE_DOWNLOAD alerts on the event topic — per-file download/save progress. These confirm download + save only, not trust-store persistence; still verify with the read-back.
Confirmation
Read back with get_installed_certificates — the installed components appear in installedCerts.certInfo[] (named {name}_{component}). This is the authoritative confirmation. (Note: private keys are never listed, and serials read back truncated to 8 bytes.)
Response Codes
install_certificate returns response.code. The codes applicable to this command are below; for the full table see the Response Codes and Correlation and Request/Response Pairing.
| Code | Description |
|---|---|
1 | Command payload is accepted (IOT_STATUS_CMD_PAYLOAD_ACCEPTED) — the success/accept code for this command. The install proceeds asynchronously; verify with get_installed_certificates. |
0 | Success — terminal success; in practice install_certificate acks with 1, and 0 is what the get_installed_certificates read-back returns. |
9 | File not found (IOT_STATUS_FILE_NOT_FOUND) — a referenced file/URL could not be found. |
21 | Certificate not found (IOT_ERROR_CERT_NOT_FOUND) — the named certificate is absent. |
23 | Invalid enum value (IOT_ERROR_INVALID_ENUM) — a field (e.g. type, certSource, authenticationType, verificationType) is outside its allowed set. |
29 | Url missing for HTTP source (IOT_ERROR_URL_MISSING) — certSource: HTTP (or defaulted) with no/empty url. |
30 | Certificate content missing for direct source (IOT_ERROR_CERT_CONTENT_MISSING) — certSource: DIRECT with no certificateBundle. |
34 | Certificate base64 decode failed (IOT_ERROR_CERT_BASE64_DECODE_FAILED) — the base64-encoded certificate content could not be decoded. Re-encode it and resend. |
36 | Missing client key or client certificate (IOT_MISSING_CLIENT_KEY_OR_CERT) — client_cert and client_key were not sent together. Always install a client certificate with its key. |
101 | Default error — generic catch-all. |
Examples
Publish install_certificate; the device acks with the code 1 envelope under Response Payload. Every contract request example is in the Certificate scenario dropdown under Request Payload, and the Result dropdown under Response Payload shows the accepted reply and the two source-specific errors (29 for a missing url, 30 for missing certificateBundle content). The examples below show what the dropdowns do not.
A DIRECT install embeds the content inline — the private key and any key password are masked:
A minimal filestore HTTP install downloads a single CA:
Notes and Caveats
Installing a certificate leaves the active MDM/MGMT control session intact. After installing, reference the certificate by its logical name from config_endpoint or set_wifi. For the concept-level view, see TLS and Authentication and Certificate Management.
Related: 📕 TLS and Authentication · 📕 get_installed_certificates · 📕 delete_certificate · 📕 config_endpoint · 📕 set_wifi · 📕 Response Codes