Skip to main content

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 in url[].
  • DIRECT — you provide the content inline in certificateBundle.

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​

PropertyValue
Interaction PatternAsynchronous Request / Accept (device acks with code 1; completion verified out-of-band)
State ChangeSTATE-CHANGING (writes to the trust store; asynchronous)
ReversibilityREVERSIBLE (remove with delete_certificate)
Required Request Fieldscommand, requestId, certDetails (with type and authenticationType)
Applies ToEndpoint: Management (MGMT). Reader: RFD40 series, RFD90 series
API VersionV1.21 (API Version Reporting)
Relatedget_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 the ca_cert / client_cert / client_key (type mqtt) that config_endpoint references in securityParams.
  • Before Wi-Fi Enterprise — install wifi-type certificates that set_wifi references in its certificate array.
  • File-store trust — install a filestore CA used to authenticate HTTPS downloads.
  • Choose the source: use DIRECT when you can embed the content (no network dependency); use HTTP when the device can reach your file server (watch the FILE_DOWNLOAD alerts).

Topic Mapping​

MessageDirectionTopicNote
RequestApp → Reader<tenantId>/MGMT/clients/cmnd/<serial>On the management endpoint.
ResponseReader → App<tenantId>/MGMT/clients/resp/<serial>The code 1 accept. Correlated by the in-payload requestId.
EventReader → 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 (use url) or DIRECT (use certificateBundle).
  • 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, but name together with type is what identifies an installed certificate afterward: delete_certificate takes exactly that pair, and a delete that omits name removes every installed certificate of the matching type.
  • certDetails.authenticationType (request) — NONE or CERTIFICATE (certificate-authenticated download).
  • certificateBundle.client_key / cert_key_password (request) — ⚠️ secrets you send inline (DIRECT); mask them. In HTTP mode a url entry with key: cert_key_password likewise carries a plaintext password in its value. See the credential warning below.
  • response.code (response) — 1 means accepted, not installed; confirm with get_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.

You transmit private keys

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.

Request payload
Example: mqtt · HTTP · CERTIFICATE auth
{
"command": "install_certificate",
"requestId": "cert-test-001",
"certDetails": {
"type": "mqtt",
"name": "testMqttCert",
"authenticationType": "CERTIFICATE",
"certSource": "HTTP",
"verificationType": "VERIFY_HOST_AND_PEER",
"caCertificateFileContent": "-----BEGIN CERTIFICATE----- MIIDPTCCAiWgAwIBAgIUHtj1WDceNR9Nf+vZBB1Ne7sFmHkwDQYJKoZIhvcNAQEL BQAwLjEPMA0GA1UEAwwGVGVzdENBMQ4wDAYDVQQKDAVaZWJyYTELMAkGA1UEBhMC VVMwHhcNMjYwNTExMTMxNDQ3WhcNMzYwNTA4MTMxNDQ3WjAuMQ8wDQYDVQQDDAZU ZXN0Q0ExDjAMBgNVBAoMBVplYnJhMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBANR8E/mxoQ5uTPW/muWnGoWDM7+YH5lIJiCM/n92 dMLIQ+TVgb9mcOz80VnpgkQqomhbZaIG4CtnBufyIJvNKid+mgrrFh18HtMnE78d lGoPC4M469Rm+0oEN9GkUHgtgF2N4Qt9bYomySux3yyPlFuUOC+uaYRCCn3Hm8ko XE/a7XWdXeJkpIB0Mzzf7MoNq14AfX431RKgvpMgAqZTnDWtm4TVnK9Hq0t64tP7 aKIAJV2avJd87dF8x+K80kLBErDnKtuNFpXN7KoC7BBwdTzbG8VWYNUZeG8eCqBh eL9MY5Ik7POmR0AM/TxRBLAXyoZHSPdEpEoaQZjSzJ7IHv0CAwEAAaNTMFEwHQYD VR0OBBYEFJHms5XPEyFYnVcf2++X9N8UlkahMB8GA1UdIwQYMBaAFJHms5XPEyFY nVcf2++X9N8UlkahMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB AL4HEEMhuQ9sQLFE9wiGw4BIILxnX30FbphWM8/xpHKuYNsH/NOWpjulG+ZAxe8n +QUhaU9hruBEajT7mYjKvZ9NtUumcAmAh3s29KD4NpjwglqUYfKQpzT4QxkcMXuW zCmqlAqGVzK3ve/Fuurgdbk3kApOZTTyqFw629dmmRhoP+2sdCYMAukyf348/4Gl Y6ZtwwAJygC4/WCfWg/7XaeQ+6kqKtY6ijSJFfCNwEPPY7CW3XAqP+kZ0e2taL5a rvm5UUPRMGCs20JOucntSF8uPOICNWUEr3DbqAJ4jXKhSHdsG6fNDyJIOzX1zn0j Vqh5mX6k2PZe0eylcukyu/s= -----END CERTIFICATE-----",
"url": [
{
"key": "ca_cert",
"value": "https://192.168.0.104:8443/mqtt_ca_cert.pem"
},
{
"key": "client_cert",
"value": "https://192.168.0.104:8443/mqtt_client_cert.pem"
},
{
"key": "client_key",
"value": "https://192.168.0.104:8443/mqtt_client_key.pem"
}
]
}
}

Request Semantics​

Modes. certDetails.certSource selects how the certificate content is supplied — HTTP (download) or DIRECT (inline):

  • HTTP (default). Supply url[] with a {key, value} entry per component (ca_cert, client_cert, client_key, cert_key_password). The device downloads each; for authenticationType: CERTIFICATE over HTTPS, supply caCertificateFileContent (or rely on an installed filestore CA). Requires device → file-server reachability; missing url returns code 29. The device emits FILE_DOWNLOAD alerts as it fetches.
  • DIRECT. Supply certificateBundle with inline PEM content for one type. No network dependency; missing certificateBundle returns code 30.

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 accepts client, server, mqtt, wifi, and filestore. Current deployments need wifi (Enterprise EAP, referenced by set_wifi), filestore (the CA that authenticates HTTPS downloads), and mqtt (broker TLS, referenced by config_endpoint). client and server are 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 pair type: client with an agent certificate (name: exampleAgent).
  • One install, one type — and file-store trust must be typed filestore. certDetails.type is a single string with a five-member enum, not a list, and certificateBundle supplies certificate content "for one certificate type", so each install_certificate call installs exactly one category. A file-store CA is therefore typed filestore and cannot also be typed client or server — send a second install_certificate if you need a second category. This matters for HTTPS downloads: with authenticationType: CERTIFICATE and an empty caCertificateFileContent, the schema names an already-installed filestore certificate as the trust anchor the device falls back to, so installing the same CA under client or server leaves no filestore entry for that fallback to use.
  • type and authenticationType are required but not firmware-enforced. The schema requires both within certDetails, but the device accepts a payload omitting them (still returns code 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.

Response payload
Example: accepted (code 1)
{
"command": "install_certificate",
"requestId": "18996",
"apiVersion": "V1.1",
"response": {
"code": 1,
"description": "Command payload is accepted"
}
}

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.

CodeDescription
1Command payload is accepted (IOT_STATUS_CMD_PAYLOAD_ACCEPTED) — the success/accept code for this command. The install proceeds asynchronously; verify with get_installed_certificates.
0Success — terminal success; in practice install_certificate acks with 1, and 0 is what the get_installed_certificates read-back returns.
9File not found (IOT_STATUS_FILE_NOT_FOUND) — a referenced file/URL could not be found.
21Certificate not found (IOT_ERROR_CERT_NOT_FOUND) — the named certificate is absent.
23Invalid enum value (IOT_ERROR_INVALID_ENUM) — a field (e.g. type, certSource, authenticationType, verificationType) is outside its allowed set.
29Url missing for HTTP source (IOT_ERROR_URL_MISSING) — certSource: HTTP (or defaulted) with no/empty url.
30Certificate content missing for direct source (IOT_ERROR_CERT_CONTENT_MISSING) — certSource: DIRECT with no certificateBundle.
34Certificate base64 decode failed (IOT_ERROR_CERT_BASE64_DECODE_FAILED) — the base64-encoded certificate content could not be decoded. Re-encode it and resend.
36Missing 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.
101Default 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:

Request — DIRECT (inline, secrets masked)
{
"command": "install_certificate",
"requestId": "cert-test-003",
"certDetails": {
"type": "mqtt",
"name": "testMqttCert",
"authenticationType": "NONE",
"certSource": "DIRECT",
"verificationType": "VERIFY_HOST_AND_PEER",
"certificateBundle": {
"ca_cert": "-----BEGIN CERTIFICATE----- … -----END CERTIFICATE-----",
"client_cert": "-----BEGIN CERTIFICATE----- … -----END CERTIFICATE-----",
"client_key": "-----BEGIN RSA PRIVATE KEY----- ******** -----END RSA PRIVATE KEY-----",
"cert_key_password": "XXXXXXXX"
}
}
}

A minimal filestore HTTP install downloads a single CA:

Request — filestore (HTTP, single CA)
{
"command": "install_certificate",
"requestId": "19001",
"certDetails": {
"name": "root_certs",
"type": "filestore",
"authenticationType": "NONE",
"certSource": "HTTP",
"verificationType": "VERIFY_HOST_AND_PEER",
"url": [
{
"key": "ca_cert",
"value": "https://192.0.2.107:8080/filestore_ca_cert.pem"
}
]
}
}

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

Was this helpful?