Overview
Two client-mode connectors for Azure Digital Twins:- AzureDigitalTwins calls your instance’s data plane (
https://<instance>.api.<region>.digitaltwins.azure.net, api-version2023-10-31). Use it to keep a twin graph in step with the plant: patch twin properties from UNS telemetry, create or replace twins and relationships, query the graph, and publish telemetry on a twin so ADT event routes forward it to Event Grid, Event Hubs or Service Bus. - AzureDigitalTwinsEntraToken calls Microsoft Entra ID (
login.microsoftonline.com) with the client-credentials flow and returns an access token for thehttps://digitaltwins.azure.netaudience.
Topics use
cloud-iot/azure-digital-twins/<object>/<verb>; replies land on <topic>/response. Before deploying, replace YOUR_INSTANCE.api.YOUR_REGION in the AzureDigitalTwins connector with your instance host name, shown as Host name on the instance overview in the Azure portal or by az dt show, for example plant-porto.api.weu.digitaltwins.azure.net.
Authentication
Every data-plane event sends a Microsoft Entra ID access token asAuthorization: Bearer <token>. The token must be issued for the Azure Digital Twins audience https://digitaltwins.azure.net.
- Register an app in Microsoft Entra ID (or use a managed identity if the broker runs on Azure) and create a client secret.
- On the Azure Digital Twins instance, assign that identity Azure Digital Twins Data Owner for read and write, or Azure Digital Twins Data Reader for read only. Owning the Azure subscription is not enough; the data-plane role is required.
- Publish
tenant_id,client_idandclient_secrettocloud-iot/azure-digital-twins/token/get. The reply carriesaccess_tokenandexpires_in(about one hour). The client secret must be URL-encoded because it goes into a form body. - Pass
access_tokenon every data-plane payload. Refresh it before it expires; the helper actions below do this every 45 minutes.
401. A valid token without the data-plane role returns 403.
Basic Syntax
MQTT examples
Request bodies go underbody, so control fields like access_token, twin_id and message_id are not sent to Azure.
Patch a twin from telemetry: publish to cloud-iot/azure-digital-twins/twin/update:
204 with an empty body. replace fails with 400 if the property has never been set on the twin, so use add for the first write. Every property must exist in the twin’s DTDL model.
Create or replace a twin: publish to cloud-iot/azure-digital-twins/twin/upsert:
cloud-iot/azure-digital-twins/relationship/upsert:
cloud-iot/azure-digital-twins/query/run:
value (the matching twins) and continuationToken. Send {"continuationToken": "..."} as the body to get the next page.
Send telemetry on a twin: publish to cloud-iot/azure-digital-twins/telemetry/send:
cloud-iot/azure-digital-twins/event-route/list). message_id must be unique per message; ADT uses it to drop duplicates.
Read: publish {"access_token": "<token>", "twin_id": "press-01"} to cloud-iot/azure-digital-twins/twin/get or .../relationship/list, {"access_token": "<token>"} to .../model/list or .../event-route/list, and {"access_token": "<token>", "model_id": "dtmi%3Acoreflux%3AMachine%3B1"} to .../model/get. URL-encode the model id because it contains : and ;.
Helper actions
Keep the Entra credentials in broker secrets, refresh the token on a timer and keep it in broker-internal state, so machines only publish their raw values:press-01 in plant/porto/line1/press-01/temperature) is the twin id. Name twins after your UNS asset ids so this mapping stays trivial. Store a client secret that is already URL-encoded, or encode it before publishing. Restrict who can read cloud-iot/azure-digital-twins/# with a rule: these payloads carry tokens and secrets.
Notes
- Errors come back on the response topic:
401for a missing, expired or wrong-audience token,403without the Data Owner or Data Reader role,404(DigitalTwinNotFound,RelationshipNotFound,ModelNotFound),400for a bad JSON Patch, a property that is not in the DTDL model or an invalid query,412for a failedIf-Match/If-None-Matchprecondition,429when throttled. - ADT throttles requests per instance and per twin (see Azure Digital Twins service limits). Batch high-rate telemetry or use
ON CHANGEinstead of patching on every sample. PATCHandPUThere send noIf-Match/If-None-Matchheader, so they overwrite unconditionally. Add the header to the event if you need optimistic concurrency.- Model upload and decommission, deletes, import and delete jobs, event connector writes, component telemetry and component patches, and the ARM control plane (creating instances) are not part of this template.

