Skip to content

Group Operations

Operations for managing groups (movies/collections).

Bases: StashClientProtocol

Mixin for group-related client methods.

Functions

find_group async

find_group(group_id: str) -> Group | None

Find a group by ID.

Parameters:

Name Type Description Default
group_id str

Group ID to search for

required

Returns:

Type Description
Group | None

Group object if found, None otherwise

Examples:

group = await client.find_group("123")
if group:
    print(f"Found group: {group.name}")
    print(f"Duration: {group.duration} seconds")
    print(f"Director: {group.director}")

Access group relationships:

group = await client.find_group("123")
if group:
    # Get scene titles
    scene_titles = [s.title for s in group.scenes]
    # Get studio name
    studio_name = group.studio.name if group.studio else None
    # Get tag names
    tags = [t.name for t in group.tags]
    # Get sub-groups
    sub_groups = [sg.group.name for sg in group.sub_groups]

find_groups async

find_groups(
    filter_: dict[str, Any] | None = None,
    group_filter: dict[str, Any] | None = None,
    ids: list[str] | None = None,
    q: str | None = None,
) -> FindGroupsResultType

Find groups matching the given filters.

Parameters:

Name Type Description Default
filter_ dict[str, Any] | None

Optional general filter parameters: - q: str (search query) - direction: SortDirectionEnum (ASC/DESC) - page: int - per_page: int - sort: str (field to sort by)

None
group_filter dict[str, Any] | None

Optional group-specific filter: - name: StringCriterionInput - director: StringCriterionInput - synopsis: StringCriterionInput - duration: IntCriterionInput - rating100: IntCriterionInput - date: DateCriterionInput - url: StringCriterionInput - is_missing: str (what data is missing) - studios: HierarchicalMultiCriterionInput - tags: HierarchicalMultiCriterionInput

None
ids list[str] | None

Optional list of group IDs to filter by

None
q str | None

Optional search query (alternative to filter_["q"])

None

Returns:

Type Description
FindGroupsResultType

FindGroupsResultType containing: - count: Total number of matching groups - groups: List of Group objects

Examples:

Find all groups:

result = await client.find_groups()
print(f"Found {result.count} groups")
for group in result.groups:
    print(f"- {group.name}")

Search by name:

result = await client.find_groups(q="Action")
print(f"Found {result.count} groups matching 'Action'")

Find groups by filter:

result = await client.find_groups(
    group_filter={
        "name": {
            "value": "Series",
            "modifier": "INCLUDES"
        }
    }
)

Find groups with specific tags:

result = await client.find_groups(
    group_filter={
        "tags": {
            "value": ["tag1", "tag2"],
            "modifier": "INCLUDES_ALL"
        }
    }
)

Find groups with high rating and sort by name:

result = await client.find_groups(
    filter_={
        "direction": "ASC",
        "sort": "name",
    },
    group_filter={
        "rating100": {
            "value": 80,
            "modifier": "GREATER_THAN"
        }
    }
)

Paginate results:

result = await client.find_groups(
    filter_={
        "page": 1,
        "per_page": 25,
    }
)

Find specific groups by IDs:

result = await client.find_groups(ids=["123", "456", "789"])

create_group async

create_group(group: Group) -> Group

Create a new group in Stash.

Parameters:

Name Type Description Default
group Group

Group object with the data to create. Required fields: - name: Group name

required

Returns:

Type Description
Group

Created Group object with ID and any server-generated fields

Raises:

Type Description
ValueError

If the group data is invalid

TransportError

If the request fails

Examples:

Create a basic group:

group = Group(name="Test Series")
created = await client.create_group(group)
print(f"Created group with ID: {created.id}")

Create group with metadata:

group = Group(
    name="Action Movie Series",
    director="John Director",
    synopsis="An action-packed series",
    duration=7200,
    date="2020-01-01",
    rating100=85,
)
created = await client.create_group(group)

Create group with relationships:

from stash_graphql_client.types import Tag, Studio

# Fetch tags and studio
tag1 = await client.find_tag("tag1_id")
tag2 = await client.find_tag("tag2_id")
studio = await client.find_studio("studio_id")

group = Group(
    name="Tagged Group",
    tags=[tag1, tag2],
    studio=studio,
)
created = await client.create_group(group)

update_group async

update_group(group: Group) -> Group

Update an existing group in Stash.

Parameters:

Name Type Description Default
group Group

Group object with updated data. Must include ID field.

required

Returns:

Type Description
Group

Updated Group object

Raises:

Type Description
ValueError

If the group ID is missing or data is invalid

TransportError

If the request fails

Examples:

Update group name and director:

group = await client.find_group("123")
group.name = "Updated Name"
group.director = "New Director"
updated = await client.update_group(group)

Update group rating:

group = await client.find_group("123")
group.rating100 = 90
updated = await client.update_group(group)

Update group tags:

group = await client.find_group("123")
tag1 = await client.find_tag("tag1_id")
tag2 = await client.find_tag("tag2_id")
group.tags = [tag1, tag2]
updated = await client.update_group(group)

group_destroy async

group_destroy(
    input_data: GroupDestroyInput | dict[str, Any],
) -> bool

Delete a group from Stash.

Parameters:

Name Type Description Default
input_data GroupDestroyInput | dict[str, Any]

GroupDestroyInput or dict with: - id: Group ID to delete

required

Returns:

Type Description
bool

True if deletion was successful

Raises:

Type Description
TransportError

If the request fails

Examples:

Delete by ID using dict:

result = await client.group_destroy({"id": "123"})
if result:
    print("Group deleted successfully")

Delete using GroupDestroyInput:

from stash_graphql_client.types import GroupDestroyInput

input_data = GroupDestroyInput(id="123")
result = await client.group_destroy(input_data)

groups_destroy async

groups_destroy(ids: list[str]) -> bool

Delete multiple groups from Stash.

Parameters:

Name Type Description Default
ids list[str]

List of group IDs to delete

required

Returns:

Type Description
bool

True if deletion was successful

Raises:

Type Description
TransportError

If the request fails

Examples:

result = await client.groups_destroy(["123", "456", "789"])
if result:
    print("Groups deleted successfully")

bulk_group_update async

bulk_group_update(
    input_data: BulkGroupUpdateInput | dict[str, Any],
) -> list[Group]

Bulk update multiple groups.

Parameters:

Name Type Description Default
input_data BulkGroupUpdateInput | dict[str, Any]

BulkGroupUpdateInput or dict with: - ids: List of group IDs to update - rating100: Optional rating (1-100) - studio_id: Optional studio ID - director: Optional director name - urls: Optional list of URLs - tag_ids: Optional list of tag IDs - containing_groups: Optional groups that contain these groups - sub_groups: Optional sub-groups

required

Returns:

Type Description
list[Group]

List of updated Group objects

Raises:

Type Description
TransportError

If the request fails

Examples:

Update rating for multiple groups:

result = await client.bulk_group_update({
    "ids": ["1", "2", "3"],
    "rating100": 85
})
print(f"Updated {len(result)} groups")

Add tags to multiple groups:

from stash_graphql_client.types import BulkGroupUpdateInput

input_data = BulkGroupUpdateInput(
    ids=["1", "2", "3"],
    tag_ids=["tag1", "tag2"]
)
result = await client.bulk_group_update(input_data)

Set studio for multiple groups:

result = await client.bulk_group_update({
    "ids": ["1", "2", "3"],
    "studio_id": "studio_123"
})

add_group_sub_groups async

add_group_sub_groups(
    input_data: GroupSubGroupAddInput | dict[str, Any],
) -> bool

Add sub-groups to a group.

Parameters:

Name Type Description Default
input_data GroupSubGroupAddInput | dict[str, Any]

GroupSubGroupAddInput or dict with: - containing_group_id: ID of the parent group - sub_groups: List of GroupDescriptionInput dicts with group_id and optional description - insert_index: Optional index at which to insert (default: append to end)

required

Returns:

Type Description
bool

True if successful

Raises:

Type Description
TransportError

If the request fails

Examples:

Add sub-groups to end:

result = await client.add_group_sub_groups({
    "containing_group_id": "parent_123",
    "sub_groups": [
        {"group_id": "child_456"},
        {"group_id": "child_789", "description": "Episode 1"}
    ]
})

Insert sub-groups at specific index:

from stash_graphql_client.types import (
    GroupSubGroupAddInput,
    GroupDescriptionInput
)

input_data = GroupSubGroupAddInput(
    containing_group_id="parent_123",
    sub_groups=[
        GroupDescriptionInput(group_id="child_456", description="Episode 2")
    ],
    insert_index=1
)
result = await client.add_group_sub_groups(input_data)

remove_group_sub_groups async

remove_group_sub_groups(
    input_data: GroupSubGroupRemoveInput | dict[str, Any],
) -> bool

Remove sub-groups from a group.

Parameters:

Name Type Description Default
input_data GroupSubGroupRemoveInput | dict[str, Any]

GroupSubGroupRemoveInput or dict with: - containing_group_id: ID of the parent group - sub_group_ids: List of sub-group IDs to remove

required

Returns:

Type Description
bool

True if successful

Raises:

Type Description
TransportError

If the request fails

Examples:

Remove sub-groups:

result = await client.remove_group_sub_groups({
    "containing_group_id": "parent_123",
    "sub_group_ids": ["child_456", "child_789"]
})

Using typed input:

from stash_graphql_client.types import GroupSubGroupRemoveInput

input_data = GroupSubGroupRemoveInput(
    containing_group_id="parent_123",
    sub_group_ids=["child_456", "child_789"]
)
result = await client.remove_group_sub_groups(input_data)

reorder_sub_groups async

reorder_sub_groups(
    input_data: ReorderSubGroupsInput | dict[str, Any],
) -> bool

Reorder sub-groups within a group.

Parameters:

Name Type Description Default
input_data ReorderSubGroupsInput | dict[str, Any]

ReorderSubGroupsInput or dict with: - group_id: ID of the parent group - sub_group_ids: List of sub-group IDs to reorder (must be subset of existing) - insert_at_id: Sub-group ID at which to insert the reordered groups - insert_after: If True, insert after insert_at_id; if False, insert before

required

Returns:

Type Description
bool

True if successful

Raises:

Type Description
TransportError

If the request fails

Examples:

Reorder sub-groups:

result = await client.reorder_sub_groups({
    "group_id": "parent_123",
    "sub_group_ids": ["child_2", "child_3"],
    "insert_at_id": "child_1",
    "insert_after": True
})

Using typed input:

from stash_graphql_client.types import ReorderSubGroupsInput

input_data = ReorderSubGroupsInput(
    group_id="parent_123",
    sub_group_ids=["child_2", "child_3"],
    "insert_at_id": "child_1",
    insert_after=False
)
result = await client.reorder_sub_groups(input_data)