Documentation Index

Fetch the complete documentation index at: https://docs.darwinium.com/llms.txt

Use this file to discover all available pages before exploring further.

Python Label management SDK

Prev Next

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.
Image

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

Image

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")