Use the Azure Digital Twins APIs and SDKs

Azure Digital Twins comes equipped with both control plane APIs and data plane APIs for managing your instance and its elements.

  • The control plane APIs are Azure Resource Manager (ARM) APIs, and cover resource management operations like creating and deleting your instance.
  • The data plane APIs are Azure Digital Twins APIs, and are used for data management operations like managing models, twins, and the graph.

This article gives an overview of the APIs available, and the methods for interacting with them. You can either use the REST APIs directly with their associated Swaggers, or through an SDK.

Overview: control plane APIs

The control plane APIs are ARM APIs used to manage your Azure Digital Twins instance as a whole, so they cover operations like creating or deleting your entire instance. You will also use these to create and delete endpoints.

The most current control plane API version for public preview is 2020-10-31.

To use the control plane APIs:

You can also exercise control plane APIs by interacting with Azure Digital Twins through the Azure portal and CLI.

Overview: data plane APIs

The data plane APIs are the Azure Digital Twins APIs used to manage the elements within your Azure Digital Twins instance. They include operations like creating routes, uploading models, creating relationships, and managing twins. They can be broadly divided into the following categories:

  • DigitalTwinModels - The DigitalTwinModels category contains APIs to manage the models in an Azure Digital Twins instance. Management activities include upload, validation, retrieval, and deletion of models authored in DTDL.
  • DigitalTwins - The DigitalTwins category contains the APIs that let developers create, modify, and delete digital twins and their relationships in an Azure Digital Twins instance.
  • Query - The Query category lets developers find sets of digital twins in the twin graph across relationships.
  • Event Routes - The Event Routes category contains APIs to route data, through the system and to downstream services.

The most current data plane API version for public preview is 2020-10-31.

To use the data plane APIs:

You can also exercise date plane APIs by interacting with Azure Digital Twins through the CLI.

.NET (C#) SDK (data plane)

The Azure Digital Twins .NET (C#) SDK is part of the Azure SDK for .NET. It is open source, and is based on the Azure Digital Twins data plane APIs.

Note

For more information on SDK design, see the general design principles for Azure SDKs and the specific .NET design guidelines.

To use the SDK, include the NuGet package Azure.DigitalTwins.Core with your project. You will also need the latest version of the Azure.Identity package.

  • In Visual Studio, you can add packages with the NuGet Package Manager (accessed through Tools > NuGet Package Manager > Manage NuGet Packages for Solution).

  • Using the .NET command-line tool, you can run:

    dotnet add package Azure.DigitalTwins.Core --version 1.0.0-preview.3
    dotnet add package Azure.identity
    

For a detailed walk-through of using the APIs in practice, see the Tutorial: Code a client app.

.NET SDK usage examples

Here are some code samples illustrating use of the .NET SDK.

Authenticate against the service:

// Authenticate against the service and create a client
string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>";
var credential = new DefaultAzureCredential();
DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);

Note

This sample uses DefaultAzureCredential (part of the Azure.Identity library) to authenticate users with the Azure Digital Twins instance when you run it on your local machine. With this type of authentication, the sample will search for Azure credentials within your local environment, such as a login from a local Azure CLI or in Visual Studio/Visual Studio Code.

For more on using DefaultAzureCredential and other authentication options, see How-to: Write app authentication code.

Upload a model and list models:

// Upload a model
var typeList = new List<string>();
string dtdl = File.ReadAllText("SampleModel.json");
typeList.Add(dtdl);
try {
    await client.CreateModelsAsync(typeList);
} catch (RequestFailedException rex) {
    Console.WriteLine($"Load model: {rex.Status}:{rex.Message}");
}
// Read a list of models back from the service
AsyncPageable<ModelData> modelDataList = client.GetModelsAsync();
await foreach (ModelData md in modelDataList)
{
    Console.WriteLine($"Type name: {md.DisplayName}: {md.Id}");
}

Create and query twins:

// Initialize twin metadata
BasicDigitalTwin twinData = new BasicDigitalTwin();

twinData.Id = $"firstTwin";
twinData.Metadata.ModelId = "dtmi:com:contoso:SampleModel;1";
twinData.CustomProperties.Add("data", "Hello World!");
try {
    await client.CreateDigitalTwinAsync("firstTwin", JsonSerializer.Serialize(twinData));
} catch(RequestFailedException rex) {
    Console.WriteLine($"Create twin error: {rex.Status}:{rex.Message}");  
}
 
// Run a query    
AsyncPageable<string> result = client.QueryAsync("Select * From DigitalTwins");
await foreach (string twin in result)
{
    // Use JSON deserialization to pretty-print
    object jsonObj = JsonSerializer.Deserialize<object>(twin);
    string prettyTwin = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true });
    Console.WriteLine(prettyTwin);
    // Or use BasicDigitalTwin for convenient property access
    BasicDigitalTwin btwin = JsonSerializer.Deserialize<BasicDigitalTwin>(twin);
}

See the Tutorial: Code a client app for a walk-through of this sample app code.

You can also find additional samples in the GitHub repo for the .NET (C#) SDK.

Serialization Helpers

Serialization helpers are helper functions available within the SDK for quickly creating or deserializing twin data for access to basic information. Since the core SDK methods return twin data as JSON by default, it can be helpful to use these helper classes to break the twin data down further.

The available helper classes are:

  • BasicDigitalTwin: Represents the core data of a digital twin
  • BasicRelationship: Represents the core data of a relationship
  • UpdateOperationUtility: Represents JSON Patch information used in update calls
  • WriteableProperty: Represents property metadata
Deserialize a digital twin

You can always deserialize twin data using the JSON library of your choice, like System.Test.Json or Newtonsoft.Json. For basic access to a twin, the helper classes make this a bit more convenient.

Response<string> res = client.GetDigitalTwin(twin_id);
BasicDigitalTwin twin = JsonSerializer.Deserialize<BasicDigitalTwin>(res.Value);
Console.WriteLine($"Model id: {twin.Metadata.ModelId}");

The BasicDigitalTwin helper class also gives you access to properties defined on the twin, through a Dictionary<string, object>. To list properties of the twin, you can use:

Response<string> res = client.GetDigitalTwin(twin_id);
BasicDigitalTwin twin = JsonSerializer.Deserialize<BasicDigitalTwin>(res.Value);
Console.WriteLine($"Model id: {twin.Metadata.ModelId}");
foreach (string prop in twin.CustomProperties.Keys)
{
    if (twin.CustomProperties.TryGetValue(prop, out object value))
        Console.WriteLine($"Property '{prop}': {value}");
}
Create a digital twin

Using the BasicDigitalTwin class, you can prepare data for creating a twin instance:

BasicDigitalTwin twin = new BasicDigitalTwin();
twin.Metadata = new DigitalTwinMetadata();
twin.Metadata.ModelId = "dtmi:example:Room;1";
// Initialize properties
Dictionary<string, object> props = new Dictionary<string, object>();
props.Add("Temperature", 25.0);
twin.CustomProperties = props;

client.CreateDigitalTwin("myNewRoomID", JsonSerializer.Serialize<BasicDigitalTwin>(twin));

The code above is equivalent to the following "manual" variant:

Dictionary<string, object> meta = new Dictionary<string, object>()
{
    { "$model", "dtmi:example:Room;1"}
};
Dictionary<string, object> twin = new Dictionary<string, object>()
{
    { "$metadata", meta },
    { "Temperature", 25.0 }
};
client.CreateDigitalTwin("myNewRoomID", JsonSerializer.Serialize<Dictionary<string, object>>(twin));
Deserialize a relationship

You can always deserialize relationship data using the JSON library of your choice, like System.Test.Json or Newtonsoft.Json. For basic access to a relationship, the helper classes make this a bit more convenient.

Response<string> res = client.GetRelationship(twin_id, rel_id);
BasicRelationship rel = JsonSerializer.Deserialize<BasicRelationship>(res.Value);
Console.WriteLine($"Relationship Name: {rel.Name}");

The BasicRelationship helper class also gives you access to properties defined on the relationship, through a Dictionary<string, object>. To list properties, you can use:

Response<string> res = client.GetRelationship(twin_id, rel_id);
BasicRelationship rel = JsonSerializer.Deserialize<BasicRelationship>(res.Value);
Console.WriteLine($"Relationship Name: {rel.Name}");
foreach (string prop in rel.CustomProperties.Keys)
{
    if (twin.CustomProperties.TryGetValue(prop, out object value))
        Console.WriteLine($"Property '{prop}': {value}");
}
Create a relationship

Using the BasicRelationship class, you can also prepare data for creating relationships on a twin instance:

BasicRelationship rel = new BasicRelationship();
rel.TargetId = "myTargetTwin";
rel.Name = "contains"; // a relationship with this name must be defined in the model
// Initialize properties
Dictionary<string, object> props = new Dictionary<string, object>();
props.Add("active", true);
rel.CustomProperties = props;
client.CreateRelationship("mySourceTwin", "rel001", JsonSerializer.Serialize<BasicRelationship>(rel));
Create a patch for twin update

Update calls for twins and relationships use JSON Patch structure. To create lists of JSON Patch operations, you can use the UpdateOperationsUtility class as shown below.

UpdateOperationsUtility uou = new UpdateOperationsUtility();
uou.AppendAddOp("/Temperature", 25.0);
uou.AppendAddOp("/myComponent/Property", "Hello");
// Un-set a property
uou.AppendRemoveOp("/Humidity");
client.UpdateDigitalTwin("myTwin", uou.Serialize());

General API/SDK usage notes

Note

Please note that Azure Digital Twins doesn't currently support Cross-Origin Resource Sharing (CORS). For more info about the impact and resolution strategies, see the Cross-Origin Resource Sharing (CORS) section of Concepts: Security for Azure Digital Twins solutions.

The following list provides additional detail and general guidelines for using the APIs and SDKs.

  • To use the SDK, instantiate the DigitalTwinsClient class. The constructor requires credentials that can be obtained with a variety of authentication methods in the Azure.Identity package. For more on Azure.Identity, see its namespace documentation.
  • You may find the InteractiveBrowserCredential useful while getting started, but there are several other options, including credentials for managed identity, which you will likely use to authenticate Azure functions set up with MSI against Azure Digital Twins. For more about InteractiveBrowserCredential, see its class documentation.
  • All service API calls are exposed as member functions on the DigitalTwinsClient class.
  • All service functions exist in synchronous and asynchronous versions.
  • All service functions throw an exception for any return status of 400 or above. Make sure you wrap calls into a try section, and catch at least RequestFailedExceptions. For more about this type of exception, see here.
  • Most service methods return Response<T> or (Task<Response<T>> for the asynchronous calls), where T is the class of return object for the service call. The Response class encapsulates the service return and presents return values in its Value field.
  • Service methods with paged results return Pageable<T> or AsyncPageable<T> as results. For more about the Pageable<T> class, see here; for more about AsyncPageable<T>, see here.
  • You can iterate over paged results using an await foreach loop. For more about this process, see here.
  • The underlying SDK is Azure.Core. See the Azure namespace documentation for reference on the SDK infrastructure and types.

Service methods return strongly-typed objects wherever possible. However, because Azure Digital Twins is based on models custom-configured by the user at runtime (via DTDL models uploaded to the service), many service APIs take and return twin data in JSON format.

Monitor API metrics

API metrics such as requests, latency, and failure rate can be viewed in the Azure portal.

From the portal homepage, search for your Azure Digital Twins instance to pull up its details. Select the Metrics option from the Azure Digital Twins instance's menu to bring up the Metrics page.

Screenshot showing the metrics page for Azure Digital Twins

From here, you can view the metrics for your instance and create custom views.

Next steps

See how to use the APIs to set up an Azure Digital Twins instance and authentication:

Or, walk through the steps to create a client app like the one used in this how-to: