Introduction to the Python Label Management SDK
This page describes how to use the python label SDK. The following are the main points to consider before using the SDK.
- You need to obtain API access certificates
- You need to ensure that you have the right permissions (LABEL EDIT) to invoke add/remove labels API.
Getting the API certificate to invoke the API
Please use the instructions documented in this page to configure your certificate that can be used to invoke the API.
Setting up certificates
Once the setup is complete, make sure your administrator has given the permissions to manage Labels for your certificate.
Obtaining the SDK
To access Darwinium python packages, you will require an API Token to download the SDK. A token can be obtained by going to the Darwinium Portal and clicking Preferences in the top right corner of the page.

Once in the preferences screen, click SDK Access and then click Generate Token

This will provide a username (the same as the username used to access Darwinium) and token. Note these down as they will only appear once.
Installing the library
The library can be installed by using pip. The version of the library used in the command below should match the release of darwinium release cycles.
The command to use to install the library is as follows:
pip install --extra-index-url=https://${DARWINIUM_PYPI_USERNAME}:${DARWINIUM_PYPI_PASSWORD}@packages.darwinium.com/artifactory/api/pypi/pypi-local/simple "dwn_label_management>=1.5.24"
In the above command, DARWINIUM_PYPI_USERNAME and DARWINIUM_PYPI_PASSWORD are environment variables representing the username and password/authentication token obtained for accessing the Darwinium hosted pypi repository.
Using the library
The first step to use the library is to create a label management client. The following code snippet shows how one can obtain a label management client using the certificates configured using the step above.
// Import the right classes
from dwn_label_management import (
LabelClient,
LabelClientConfig,
Label,
LabelPage,
)
// Provide a client configuration that can be used to create a client instance
client_config = LabelClientConfig(
node_name="<node_name : Obtain this from your portal administrator>",
api_endpoint_port=9443,
mtls_CA_file_path="<Local File System Path to your CA chain file as configured in the step above>",
mtls_cert_file_path="<Local File System Path to your certificate>",
mtls_key_file_path="<Local File system path to your private key>",
mtls_key_file_password="<password for your private key file>", # Optional: if your key has a password
)
// Finally create a client instance by using the above configuration definition
client = LabelClient(client_config)
Once the client is created, one can use the client APIs to manage the labels in a programmatic way. Please note that the APIS are async apis only. This essentially means that you need to await on the calls to the class methods.
Adding a label
The following code snippet gives an example as to how to add a label
# Add a account_takeover label to a username
result = await client.add_label(
label_programmatic_name="account_takeover",
attributes=[
{
"programmaticName": "identity['*'].username.username",
"value": "suspicious_user_123"
}
],
contexts=[], # Empty list for default contexts
notes="Flagged during manual review",
)
print(f"Success: {result.success}")
print(f"Label UUID: {result.uuid}")
print(f"Raw response: {result.raw_response}")
Note that the label names are the same names that are visible in the portal. Additionally one can use the other methods present in this package to list out all possible label names Please refer to the later sections in this page for more details on this method.
Adding a label with multiple attributes
This is pretty much same as the add label above but now we have additional attributes specified.
# Add a label with multiple identifying attributes
result = await client.add_label(
label_programmatic_name="account_takeover",
attributes=[
{
"programmaticName": "identity['*'].email['*'].email",
"value": "verified.customer@example.com"
},
{
"programmaticName": "identity['*'].name.first",
"value": "John"
},
{
"programmaticName": "identity['*'].name.last",
"value": "Smith"
},
],
contexts=[],
notes="Verified through customer support",
)
print(f"Success: {result.success}")
Adding labels with contexts
One can pass a list of contexts as shown in the code below while adding labels
# Add a label that applies only to specific contexts
result = await client.add_label(
label_programmatic_name="scripted_attack_fraud",
attributes=[
{
"programmaticName": "identity['*'].login.login",
"value": "bot_user_42"
}
],
contexts=["finance", "reasonable"], # Programmatic context names
notes="Detected automated login pattern",
)
print(f"Success: {result.success}")
Handling errors
All of the label APIs throw an instance of the GraphQLError if there is an issue processing the request.
from dwn_label_management import GraphQLError
try:
result = await client.add_label(
label_programmatic_name="invalid_label_name",
attributes=[
{"programmaticName": "identity['*'].email['*'].email", "value": "test@test.com"}
],
contexts=[],
)
if not result.success:
print(f"Operation failed: {result.error}")
print(f"Message: {result.message}")
else:
print(f"Label added: {result.uuid}")
except GraphQLError as e:
print(f"GraphQL error: {e.message}")
print(f"Errors: {e.errors}")
Listing labels using pagination
The following code snippet shows how to list all labels and paginate through them. The result can be stored in a pandas dataframe if needed.
# Manual pagination
page = 0
page_size = 20
all_labels : list[LabelPage]= []
while True:
result = await client.get_labels(page=page, page_size=page_size)
all_labels.extend(result.labels) # type: ignore
print(f"Page {page}: {len(result.labels)} labels (total: {result.total_count})")
if len(all_labels) >= result.total_count:
break
page += 1
# Safety limit
if page >= 10:
print("Reached page limit")
break
print(f"\nFetched {len(all_labels)} labels total")
all_labels_df = pd.DataFrame([label.dict() for label in all_labels]) # type: ignore
all_labels_df
Removing a label
You will need a UUID of the lable that needs to be deleted. Below is the example code snippet.
# Remove a label using its UUID
label_uuid = "dd2ee511ad094a9d86b0025422c78b58" # Replace with actual UUID
result = await client.remove_label(
label_uuid=label_uuid,
notes="Label no longer applicable - customer verified",
)
print(f"Success: {result.success}")
print(f"Removed UUIDs: {result.removed_uuids}")
Get all contexts that can be applied to any label
# Fetch all available contexts
contexts = await client.get_all_contexts()
print(f"Total contexts: {len(contexts)}")
print("\nFirst 10 contexts:")
for ctx in contexts[:10]:
print(f" ID {ctx.id}: {ctx.programmatic_name}")
print(f" Display: {ctx.display_name}")
print(f" Group: {ctx.group}")
print()
Group contexts by their category
from collections import defaultdict
# Group contexts by their group/category
contexts_by_group = defaultdict(list) # type: ignore
for ctx in contexts:
contexts_by_group[ctx.group].append(ctx) # type: ignore
print("Contexts by group:")
for group, group_contexts in sorted(contexts_by_group.items()): # type: ignore
print(f"\n{group or '(No Group)'}: {len(group_contexts)} contexts") # type: ignore
for ctx in group_contexts[:5]: # Show first 5 per group # type: ignore
print(f" - {ctx.programmatic_name}") # type: ignore
if len(group_contexts) > 5: # type: ignore
print(f" ... and {len(group_contexts) - 5} more") # type: ignore
Resolve Context Names to IDS
If you want to know the context IDs that can be used in the label add API, the following code snippet might be useful.
# Convert programmatic names to IDs
names_to_resolve = ["session_id", "device_fingerprint", "email", "probably"]
resolved_ids = await client.resolve_context_names(names_to_resolve)
print("Resolved IDs:")
for name, ctx_id in resolved_ids.items():
print(f" {name} -> {ctx_id}")
Fetch All Label definitions
# Fetch all label definitions
label_defs = await client.get_all_label_definitions()
print(f"Total label definitions: {len(label_defs)}")
print("\nFirst 10 label types:")
for label_def in label_defs[:10]:
print(f"\n {label_def.programmatic_name} (ID: {label_def.id})")
print(f" Display: {label_def.display_name}")
print(f" Category: {label_def.category_programmatic_name}")
print(f" Valid contexts: {len(label_def.valid_context_ids)}")
Group Label definitions by Category
# Group label definitions by category
labels_by_category = defaultdict(list) # type: ignore
for label_def in label_defs:
labels_by_category[label_def.category_programmatic_name].append(label_def) # type: ignore
print("Labels by category:")
for category, defs in sorted(labels_by_category.items()): # type: ignore
print(f"\n{category}: {len(defs)} label types") # type: ignore
for label_def in defs[:3]: # type: ignore
print(f" - {label_def.programmatic_name}") # type: ignore
if len(defs) > 3: # type: ignore
print(f" ... and {len(defs) - 3} more") # type: ignore
Getting valid contexts for a label
# Get valid contexts for a specific label type
label_type = "account_takeover" # Replace with actual label name
try:
valid_contexts = await client.get_valid_contexts_for_label(label_type)
print(f"Valid contexts for '{label_type}': {len(valid_contexts)}")
print("\nFirst 20 valid contexts:")
for ctx in valid_contexts[:20]:
print(f" - {ctx.programmatic_name} ({ctx.group})")
except ValueError as e:
print(f"Error: {e}")
Filter by Label IdS
# Query only specific label types (by label_id)
result = await client.get_labels(
page=0,
page_size=20,
label_ids=[4040, 4050, 4070], # Specific label type IDs
)
print(f"Found {result.total_count} labels matching the specified IDs")
Using Filter expressions
Use the same filter expression language that you use in the portal user interface to fetch the labels that you want to operate on.
# Query with a filter expression
result = await client.get_labels(
page=0,
page_size=20,
filter_expr="profiling.device.identifier in ('cc3ef45bdb344b57a9891a42ce65423e')",
)
print(f"Found {result.total_count} active (non-deleted) labels")