Delete Twins

When Digital Twins are no longer needed they can be deleted through the IOTICSpace user interface or the IOTICS API.

This page covers:


Introduction to Delete Digital Twins

You may wish to delete one or more Twins if you no longer need them and no other Twins are following their data feeds. You can delete Twins and Twin Models in the same way you have created them, either through the IOTICS user interface or the IOTICS API.

❗️

A Twin can be only updated and/or deleted with the credentials initially used to create the Twin

The IOTICS user interface and the IOTICS API use different credentials to create Twins. This means that, if you have created your Digital Twin through the user interface, you won't be able to delete it via the API, and vice-versa.

Delete Digital Twins

Delete a Twin with the IOTICS user interface

Navigate to the Twins section on your IOTICSpace user interface. Once you have found the Digital Twin to delete, click on the delete icon in the ACTIONS section.

Delete a Twin with the IOTICS API

Click to see the prerequisites

  1. Create your token to interact with your Host (guide);
  2. Create headers to be added alongside the API request (guide);
from requests import request

response = request(
    method="DELETE",
    url=f"{HOST}/qapi/twins/{twin_did}",  # Replace with URL of the Host and the DID of the Twin to delete
    headers=headers,  # It includes the token
)
response.raise_for_status()

Delete Digital Twin Models

Delete a Twin Model with the IOTICS user interface

Navigate to the Twin Models section on your IOTICSpace user interface. Once you have found the Model to delete, click on the delete icon in the ACTIONS section. Deleting a Model will automatically delete all the associated Twins.

Delete a Twin Model with the IOTICS API

When deleting a Twin Model, make sure you also delete all the Twins belonging to that Model. In fact, a Twin without its Model:

  • by concept is meaningless: every Twin must belong to a specific existing Twin template (e.g. Twin Model);
  • the Twin's property Twin from Model would point to a non-existing Twin DID.
Click to see the entire code on how to Delete a Twin Model along with all its Twins

import json
from datetime import datetime, timedelta, timezone
from typing import List

from iotics.lib.identity.api.high_level_api import get_rest_high_level_identity_api
from requests import request

RESOLVER_URL = "resolver_url"
HOST = "host_url"

USER_KEY_NAME = "user_key_name"
AGENT_KEY_NAME = "agent_key_name"
USER_SEED = bytes.fromhex("user_seed")
AGENT_SEED = bytes.fromhex("agent_seed")


def make_api_call(method: str, url: str, json: dict = None):
    response = request(method=method, url=url, headers=headers, json=json)
    response.raise_for_status()

    return response.json()


def get_twin_label(properties: List[str]):
    label = "unknown"

    for p in properties:
        if p["key"] == "http://www.w3.org/2000/01/rdf-schema#label":
            label = p["langLiteralValue"]["value"]
            break

    return label


def search_twins(
    properties: List[str] = None,
    text: str = None,
    location: str = None,
    scope: str = "LOCAL",
    response_type: str = "MINIMAL",
):
    # Initialise an empty list.
    # It will contain the list of Twins retrieved by the search
    twins_list = []

    headers.update(
        {
            "Iotics-RequestTimeout": (
                datetime.now(tz=timezone.utc) + timedelta(seconds=10)
            ).isoformat(),
        }
    )

    payload = {"filter": {}, "responseType": response_type}

    if properties:
        payload["filter"]["properties"] = properties
    if text:
        payload["filter"]["text"] = text
    if location:
        payload["filter"]["location"] = location

    with request(
        method="POST",
        url=f"{HOST}/qapi/searches",
        headers=headers,
        stream=True,
        verify=False,
        params={"scope": scope},
        json=payload,
    ) as resp:
        # Raises HTTPError, if one occurred
        resp.raise_for_status()
        # Iterates over the response data, one line at a time
        for chunk in resp.iter_lines():
            response = json.loads(chunk)
            twins_found = []
            try:
                twins_found = response["result"]["payload"]["twins"]
            except (KeyError, IndexError):
                continue
            finally:
                if twins_found:
                    # Append the twins found to the list of twins
                    twins_list.extend(twins_found)

    print(f"Found {len(twins_list)} twin(s)")

    headers.pop("Iotics-RequestTimeout")

    return twins_list


# Set up the API with authentication delegation so the AGENT can authenticate on behalf of the USER
api = get_rest_high_level_identity_api(resolver_url=RESOLVER_URL)
(
    user_registered_id,
    agent_registered_id,
) = api.create_user_and_agent_with_auth_delegation(
    user_seed=USER_SEED,
    user_key_name=USER_KEY_NAME,
    agent_seed=AGENT_SEED,
    agent_key_name=AGENT_KEY_NAME,
    delegation_name="#AuthDeleg",
)

token = api.create_agent_auth_token(
    agent_registered_identity=agent_registered_id,
    user_did=user_registered_id.did,
    duration=600,
)

headers = {
    "accept": "application/json",
    "Iotics-ClientAppId": "example_code",
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json",
}

print("Searching for Twin Models within the Space...")

# Search for Twin Models within the Space
twin_model_list = search_twins(
    properties=[
        {
            "key": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
            "uriValue": {"value": "https://data.iotics.com/app#Model"},
        }
    ],
    response_type="FULL",
)

twin_model_did = None

for twin_model in twin_model_list:
    twin_model_label = get_twin_label(twin_model["properties"])
    twin_did = twin_model["id"]["value"]
    answer = input(
        f"Do you want to delete {twin_model_label} with all its Twins (y/n) ? "
    )
    if answer == "y":
        twin_model_did = twin_did
        break

if twin_model_did:
    print("Searching for Twins from Model within the Space...")

    twins_from_model_list = search_twins(
        properties=[
            {
                "key": "https://data.iotics.com/app#model",
                "uriValue": {"value": twin_model_did},
            }
        ]
    )

    # Delete Twins from Model
    for twin in twins_from_model_list:
        twin_did = twin["id"]["value"]
        print(f"Deleting Twin {twin_did}")
        make_api_call(method="DELETE", url=f"{HOST}/qapi/twins/{twin_did}")

    # Finally delete the Twin Model
    print(f"Deleting Twin Model {twin_model_did}")
    make_api_call(method="DELETE", url=f"{HOST}/qapi/twins/{twin_model_did}")

Did this page help you?