config_endpoint
ReferenceAudience: API consumerUse: add, update, or delete an MQTT endpoint configuration on the reader
Overview
config_endpoint provisions the reader's MQTT endpoints — it adds, updates, or deletes an endpoint configuration (chosen by epConfig.operation). One payload defines an endpoint's type, protocol, broker url/port, TLS verificationType and certificates, MQTT keepAlive/session/reconnect settings, publish/subscribe topics, optional broker credentials, and per-endpoint event routing. It is a state-changing command on the device-management (MGMT) endpoint; the response is status-only. Read the result back with get_endpoint_config.
config_endpoint is state-changing and can carry broker credentials — and reconfiguring the endpoint that carries your own control session can sever it. See the session-sever callout in Notes and Caveats and the credential/TLS handling in Request Semantics. A saved endpoint is reversible with operation: delete.
An endpoint connects only when it is active. activate: false saves the endpoint; activate: true saves it and marks it active. With activate: true, the reader checks the endpoint’s parameters. If they are valid, it disconnects from the current configuration and connects to the new endpoint; no reboot is needed. Wait for a CONNECTED mqttConnEVT on the endpoint’s connection-state topic to confirm the connection. get_endpoint_config lists the endpoint under activeEndpoints as soon as it is stored as active, which does not show that it connected.
What happens when you add an endpoint with activate: true:
Details
| Property | Value |
|---|---|
| Interaction Pattern | Request / Response (app publishes a command; device publishes the correlated reply) |
| State Change | STATE-CHANGING (writes/removes a saved endpoint; may activate it) |
| Reversibility | REVERSIBLE (remove with operation: delete; change with operation: update) |
| Supported Operations | add (new), update (existing), delete (existing) |
| Required Request Fields | command, requestId, epConfig (with operation and configuration) |
| Applies To | Endpoint: Management (MGMT). Reader: RFD40 series, RFD90 series |
| API Version | V1.1 (API Version Reporting) |
| Related | get_endpoint_config, config_events, install_certificate, reboot |
When to Use
Use config_endpoint to provision or maintain the reader's MQTT wiring after the initial MDM endpoint exists (that first endpoint is set up with 123RFID Desktop; all others are added remotely with config_endpoint).
add— create a new endpoint (MGMT,CTRL,DATA1, …). TheendpointNamemust not already exist (duplicate → code10).update— modify an existing endpoint (e.g. changeurl, or flipactivate). TheendpointNamemust already exist.delete— remove an existing endpoint (the contract's example sends onlyendpointName+epType).- Pre-provision safely — send
activate: falseto save an endpoint without activating it, then activate later withupdate. A saved endpoint does not connect until it is active.
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> | Correlated reply; the in-payload requestId links the twin topics. |
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.
The topic values you configure inside mqttParams are base topics (e.g. MGMT/clients/resp). The reader constructs the full topic at runtime as <tenantId>/<topic>/<serial> — never include the tenant or serial in topic.
Credentials are presented once at CONNECT (and, for a configured endpoint, via mqttParams). The requestId you send is echoed in the response so you can pair reply to request.
See Topics and Channels.
Key Fields
epConfig.operation(request) —add/update/delete; determines the action.configuration.endpointName(request) — the endpoint's identity (create target / update / delete key).configuration.epType(request) — the endpoint's role (MGMT,CTRL,DATA1, …).configuration.activate(request) —truesaves the endpoint and marks it active, and the reader connects for it without a reboot if the parameters are valid;falseonly saves it.configuration.securityParams(request) — forMQTT_TLS; the referenced certificates must be pre-installed viainstall_certificate.response.code(response) — read this to determine success vs failure (see Response Codes).
Request Payload
The envelope is command, requestId, and the epConfig payload (operation + configuration). Pick an operation / endpoint below; the Example and Schema update together. Use the Schema tab for the full field reference and the Example tab for the concrete payload.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | config_endpoint | Fixed command name. |
requestId* | string | — | abc123 | A unique identifier for the request; echoed back in the response. |
epConfig* | object | — | — | The endpoint-configuration payload. Required by the contract, which also requires operation and configuration within it. |
operation*, nesting level 2 | enum | adddeleteupdate | add | add a new endpoint, update an existing one, or delete one. Required within epConfig. See Request Semantics. |
configuration*, nesting level 2 | object | — | — | The endpoint configuration. Required within epConfig. The contract requires endpointName, epType, protocol, activate, url, verificationType and port for every operation, although its own delete and update examples send fewer (see Request Semantics). |
endpointName*, nesting level 3 | string | — | mgmt | The endpoint name (its identity for add/update/delete). |
epType*, nesting level 3 | enum | MGMTMGMT_EVTCTRLDATA1DATA2MDM | MGMT | The endpoint type (its role). DATA2 is currently not supported. |
protocol*, nesting level 3 | enum | MQTTMQTT_TLS | MQTT | MQTT (plain, typically port 1883) or MQTT_TLS (TLS, typically port 8883). Both literals read back unchanged via get_endpoint_config; see Request Semantics. |
activate*, nesting level 3 | boolean | — | true | true saves the endpoint and marks it active: the reader checks its parameters and, if they are valid, connects for it without a reboot. false only saves it (activate it later with update). |
url*, nesting level 3 | string | — | broker.example.com | Broker address (host or IP). |
verificationType*, nesting level 3 | enum | VERIFY_NONEVERIFY_HOST_AND_PEER | VERIFY_HOST_AND_PEER | TLS verification mode. Required. Use VERIFY_HOST_AND_PEER; VERIFY_NONE must not be used in production, and MQTT_TLS with VERIFY_NONE returns code 37. |
port*, nesting level 3 | integer | — | 1883 | Broker port (1883 plain, 8883 TLS). |
qosCommon, nesting level 3 | integer | — | 1 | Default QoS level for the endpoint: 0 or 1, the levels the reader supports. |
tenantId, nesting level 3 | string | — | ZEBRA | Tenant identifier; the first segment of every on-wire topic. Not in any of the contract’s required sets, but send it: without it no topic resolves. Bounded at 48 characters; an overlong value returns code 27. |
mqttParams, nesting level 3 | object | — | — | MQTT connection parameters, topics, and (optional) broker credentials. |
keepAlive, nesting level 4 | integer | max 65535 | 300 | Keep-alive interval when idle. |
cleanSession, nesting level 4 | boolean | — | true | Whether to start a clean MQTT session. |
reconnectDelayMin, nesting level 4 | integer | — | 5 | Minimum reconnect back-off. |
reconnectDelayMax, nesting level 4 | integer | — | 60 | Maximum reconnect back-off. |
clientId, nesting level 4 | string | — | zebra-rfd40-01 | MQTT client ID used for the broker connection. |
username, nesting level 4 | string | — | mqttuser | Broker username, when the broker requires username authentication. Redact it in logs. |
password, nesting level 4 | string | — | — | Broker password, when the broker requires password authentication — a secret; mask it. |
publishTopics, nesting level 4 | array | — | — | Base topics the endpoint publishes to — at most 3 (exceeding returns code 25). Entries are positional: schema examples order them [0] responses, [1] events, [2] connection events and the Last Will. On DATA endpoints, firmware guidance places the tag-data topic at [1] — see Request Semantics. Each item requires topic, qos, retain. |
topic*, nesting level 5 | string | — | zebra/rfd40/01/data | Base topic only — wrapped on-wire to <tenantId>/<topic>/<serial>. Do not include tenant or serial. |
qos*, nesting level 5 | integer | — | 1 | QoS for this published topic: 0 or 1, the levels the reader supports. |
retain*, nesting level 5 | boolean | — | false | Whether the broker retains the last message. |
subscribeTopics, nesting level 4 | array | — | — | Base topics the endpoint subscribes to — up to 1 (exceeding returns code 26). Each item requires topic, qos, retain. |
topic*, nesting level 5 | string | — | zebra/rfd40/01/data | Base topic only — wrapped on-wire to <tenantId>/<topic>/<serial>. |
qos*, nesting level 5 | integer | — | 0 | QoS for this subscription: 0 or 1, the levels the reader supports. |
retain*, nesting level 5 | boolean | — | — | Retain flag for this subscription. |
securityParams, nesting level 3 | object | — | — | TLS parameters (for MQTT_TLS). Required within securityParams: format. The referenced certificates must already be installed via install_certificate. |
format*, nesting level 4 | enum | PEMPFX | PEM | Certificate format. The enum lists PEM and PFX, but only PEM is currently supported. |
caCertificateFile, nesting level 4 | string | — | cloud-trusted-ca-certs.crt | Installed CA certificate reference name (a name, not key material). |
clientCert, nesting level 4 | string | — | client_cert.pem | Installed client certificate reference name. |
clientKey, nesting level 4 | string | — | client_key.pem | Installed client key reference name. |
eventConfiguration, nesting level 3 | object | — | — | Per-endpoint event routing — the same shape as config_events, selecting which events this endpoint emits, plus optional heartbeat settings. Only 7 toggles are functional today; see Request Semantics. |
antenna, nesting level 4 | boolean | — | false | set to true to enable antenna events |
terminalConnection, nesting level 4 | boolean | — | false | set to true to enable terminal connection/disconnection events |
firmwareUpdate, nesting level 4 | boolean | — | true | set to true to enable fw update events |
gpi, nesting level 4 | boolean | — | false | set to true to enable gpi events |
network, nesting level 4 | boolean | — | true | set to true to enable network events |
exceptions, nesting level 4 | boolean | — | false | set to true to enable exception events |
ntp, nesting level 4 | boolean | — | true | set to true to enable network time alerts |
userApp, nesting level 4 | boolean | — | false | set to true to enable user app events |
heartbeat, nesting level 4 | boolean | — | false | set to true to enable heart beat |
power, nesting level 4 | boolean | — | true | set to true to enable power source alerts |
battery, nesting level 4 | boolean | — | true | set to true to enable battery alerts |
temperature, nesting level 4 | boolean | — | false | set to true to enable temperature alerts |
fileDownload, nesting level 4 | boolean | — | true | set to true to enable file download alerts |
cpuUsage, nesting level 4 | boolean | — | false | set to true to enable cpu usage alerts |
flashUsage, nesting level 4 | boolean | — | false | set to true to enable flash usage alerts |
ramUsage, nesting level 4 | boolean | — | false | set to true to enable ram usage alerts |
heartbeatConfiguration, nesting level 4 | object | — | — | Heartbeat settings; set them when heartbeat is true. |
interval, nesting level 5 | integer | max 65535 | 100 | Seconds between heartbeats, at most 65,535. |
inventoryStatus, nesting level 5 | boolean | — | true | set to true to enable inventory status as part of heartbeat message |
batteryStatus, nesting level 5 | boolean | — | true | set to true to enable battery status as part of heartbeat message |
userApps, nesting level 5 | boolean | — | — | set to true to enable user app status as part of heartbeat message |
cpuThreshold, nesting level 4 | integer | — | 0 | cpu usage value(%) above which alert will be triggered |
ramThreshold, nesting level 4 | integer | — | 0 | ram usage value(%) above which alert will be triggered |
flashThreshold, nesting level 4 | integer | — | 0 | flash usage value(%) above which alert will be triggered |
temperatureThreshold, nesting level 4 | integer | — | 0 | temperature treshold value above which alert will be triggered |
batching, nesting level 3 | object | — | — | Report batching for this endpoint. Optional; when absent, the reader's built-in batching applies and no source states what that is. A report is published when either limit is reached. |
reportingInterval, nesting level 4 | integer | 1000–60000 | 5000 | Reporting timeout for batching tags, in milliseconds. 0 falls back to the minimum, 1000. |
maxPayloadSizePerReport, nesting level 4 | integer | 1024–5120 | 1024 | Maximum payload size per report, in bytes. 0 falls back to the minimum, 1024. |
Request Semantics
Modes. epConfig.operation selects the action. The contract requires the same seven configuration fields for every operation — endpointName, epType, protocol, activate, url, verificationType and port — but its own delete example sends only endpointName and epType, and its update example omits verificationType and port. A validator built strictly from the contract rejects both examples; this is a known issue in the source schema:
add— creates a new endpoint. Supply the fullconfiguration(the 7 fieldsaddrequires —endpointName,epType,protocol,activate,url,verificationType,port— plus optionalmqttParams/securityParams/eventConfiguration). Fails with code10if theendpointNamealready exists.update— modifies an existing endpoint (matched byendpointName). The contract's example sendsendpointNameandepTypeplus the fields being changed.delete— removes an existing endpoint. The contract's example sends onlyendpointNameandepType.
add is not idempotent. If a response is lost (e.g. a timeout), the endpoint may already have been created — read back with get_endpoint_config before retrying rather than blindly re-sending, or the retry will be a duplicate add.
- Payloads can carry broker credentials.
mqttParams.username/passwordare supplied in the request when the broker requires them — masked in the example on this page. Redact them in logs, tickets, and screenshots, and sendconfig_endpointonly over secured channels. (Certificate fields —caCertificateFile/clientCert/clientKey— are reference names of already-installed certificates, not key material.) - Optional MQTT connection fields.
mqttParams.clientIdsets the MQTT client ID used for the broker connection;cleanSessiondefaults totrue. - TLS needs pre-installed certificates. For
protocol: MQTT_TLS, thesecurityParamscaCertificateFile/clientCert/clientKeymust reference certificates already installed viainstall_certificate. Onlyformat: PEMis supported today. The protocol literal is spelledMQTT_TLSin both directions — one enum governs the request and theget_endpoint_configread-back — so send and match it exactly. - Topic slots are positional.
publishTopicsaccepts at most 3 entries (exceeding → code25) andsubscribeTopicsat most 1 (exceeding → code26); both arrays are optional — the contract's ownDATA1read-back returnssubscribeTopics: []. The three publish slots carry command responses (…/clients/resp), events — heartbeat, alerts (…/clients/event), then the endpoint's connection-event topic (…/clients/rfid, which carriesmqttConnEVT);subscribeTopics[0]is command ingress, where the host publishes and the reader subscribes (…/clients/cmnd). Position is what routes — the reader binds each entry by index, not by base name — so keep the configured order, leave omitted indices unused, and match aget_endpoint_configread-back by index rather than by topic name. Configure only the basetopic; the reader wraps it as<tenantId>/<topic>/<serial>. - DATA endpoints: put the tag-data topic at
publishTopics[1]. OnepTypeDATA1the reader streams tag data from the second publish entry (DATA2is currently not supported), so configure an unused placeholder at[0]and the tag-data topic (e.g.DATA/clients/data1event) at[1]:[{ "topic": "DATA/clients/unused", "qos": 0, "retain": false }, { "topic": "DATA/clients/data1event", "qos": 1, "retain": false }]. EveryDATA1example on this page uses this two-entry layout. A single-entry array is the trap: the one entry lands in the reply slot, theaddstill succeeds, and no tag data ever arrives. A read-back showingactivate: trueshows only that the endpoint is stored as active; it does not show that the endpoint connected or that tag data is flowing. verificationType: useVERIFY_HOST_AND_PEER. It verifies the broker's certificate chain and that the certificate matches the host.VERIFY_NONEturns verification off; use it only on an isolated test network, and never on anMQTT_TLSendpoint, which rejects it with code37.get_endpoint_configreads back the value you sent, so a client doing read-modify-write can echo it.- Event routing.
configuration.eventConfigurationuses the same shape asconfig_events; only 7 of its toggles are functional today (the rest are reserved). See the Event routing fields table on theget_endpoint_configpage for the full supported-vs-reserved split.
Topic slots by epType. How the positional layout above lands per endpoint type. The contract's examples show the command/response layout; the data-endpoint layout (†) is firmware guidance that the contract does not state:
epType | publishTopics[0] | publishTopics[1] | publishTopics[2] | subscribeTopics[0] |
|---|---|---|---|---|
MGMT · MDM | command responses (…/resp) | events (…/event) | connection events (…/rfid) | command ingress (…/cmnd) |
CTRL | command responses (…/resp) | stored, not used for events | connection events (…/rfid) | command ingress (…/cmnd) |
MGMT_EVT | not used | not used | Last Will | events are currently published here (a firmware defect) |
DATA1 | unused placeholder † | tag-data stream (…/data1event) † | — | — (does not subscribe) |
The command/response endpoints (MGMT, MDM, CTRL) share the [0] and [2] layout; on CTRL, slot [1] is stored but not used for events. A MGMT_EVT endpoint currently publishes its events on its subscribe topic instead of publishTopics[1], which the API owners record as a firmware defect; see Endpoints and Topic Slots. Match read-back entries by index, not by base name — the resp / event / rfid names are conventions.
† Tag data binds to publishTopics[1], so a data endpoint needs a throwaway entry at [0] to push the real topic into slot [1] — see the DATA-endpoint bullet above.
Response Payload
config_endpoint returns a status-only envelope — command, requestId, apiVersion, and response. There is no configuration echo; confirm the change with get_endpoint_config.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | config_endpoint | 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 | — | — | Status-only result — config_endpoint echoes no configuration. |
code*, nesting level 2 | integer | 0–101 | 0 | 0 = Success; non-zero = error. Required by the contract. See Response Codes below. |
description*, nesting level 2 | string | — | Success | Human-readable status. |
Response Codes
config_endpoint 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 |
|---|---|
0 | Success — the endpoint was added, updated, or deleted. |
10 | Configuration already exists (IOT_ERROR_CONFIG_ALREADY_EXIST) — an add used an endpointName that already exists. Use update, or delete it first. |
23 | Invalid enum value (IOT_ERROR_INVALID_ENUM) — a field (e.g. operation, epType, protocol, verificationType, format) is outside its allowed set. |
25 | Max 3 publish topics exceeded (IOT_ERROR_PUBLISH_TOPICS_EXCEEDED) — more than 3 publishTopics. |
26 | Max 1 subscribe topic exceeded (IOT_ERROR_SUBSCRIBE_TOPIC_EXCEEDED) — more than 1 subscribeTopics. |
27 | Invalid tenant ID length (IOT_ERROR_INVALID_TENANTID_LENGTH) — tenantId exceeds the allowed length. |
33 | Endpoint already configured (IOT_ERROR_ENDPOINT_ALREADY_CONFIGURED) — an endpoint with the same configuration already exists. |
35 | Can't modify an active endpoint (IOT_ERROR_CANT_MODIFY_ACTIVE_ENDPOINT) — the target endpoint is currently active. Deactivate it before modifying it. |
37 | Invalid verification type for MQTT TLS (IOT_INVALID_MQTT_TLS_VERIFICATION_TYPE) — protocol: MQTT_TLS was sent with verificationType: VERIFY_NONE. Use VERIFY_HOST_AND_PEER. |
101 | Default error — generic catch-all. See the duplicate-add note below. |
Duplicate add may return the generic 101. The documented code for adding an endpointName that already exists is 10 ("Configuration already exists"), but the firmware has been observed returning the generic 101 ("Default error") for a duplicate add instead of 10. Treat a 101 after a re-sent add as a probable duplicate and verify with get_endpoint_config.
Examples
Publish a config_endpoint request; the device replies with the status-only envelope under Response Payload. Every contract example — each add, the delete and the partial update — is in the Operation / endpoint dropdown under Request Payload. The examples below show what the dropdown does not.
A plain-MQTT DATA1 add with broker credentials (activate: true), the tag-data topic at publish slot [1] with an unused placeholder at [0] — the layout the firmware guidance under Request Semantics describes — and no TLS:
A duplicate add returns code 10 (or, on some firmware, the generic 101 — see the note above):
Notes and Caveats
Activating a new endpoint of a different role coexists with the endpoint carrying your control session (e.g. activating a DATA1 endpoint does not drop the MDM/MGMT control channel). But changing the broker url/port/protocol of — or deleting — the endpoint that carries your own control session can sever it. When in doubt, save with activate: false and switch deliberately.
Because the response is status-only, verify the result with get_endpoint_config — confirm the endpoint appears in savedEndpoints.epNames[] and (if activate: true) under activeEndpoints. A CONNECTED mqttConnEVT on the endpoint’s connection-state topic confirms that it connected. For the concept-level view, see Endpoints and Topic Slots.
Related: 📕 Endpoints and Topic Slots · 📕 get_endpoint_config · 📕 config_events · 📕 install_certificate · 📕 Response Codes