Skip to content

Items

CRUD operations for Homebox items, including attachments, maintenance entries, custom fields, and bulk import/export.

ItemsClient

Sub-client for item CRUD, attachment, and maintenance-log endpoints.

Accessed via HomeboxClient.items.

Source code in homebox/client.py
class ItemsClient:
    """Sub-client for item CRUD, attachment, and maintenance-log endpoints.

    Accessed via ``HomeboxClient.items``.
    """

    def __init__(self, client: HomeboxClient):
        """Initialise the items sub-client with the shared root client."""
        self.client = client

    @staticmethod
    def _normalize_tag_payload(payload: dict[str, Any]) -> dict[str, Any]:
        """Map legacy label keys to v23 tag keys for compatibility."""
        if "labelIds" in payload and "tagIds" not in payload:
            payload["tagIds"] = payload.pop("labelIds")
        else:
            payload.pop("labelIds", None)
        return payload

    @staticmethod
    def _unwrap_item_response(response: dict[str, Any]) -> dict[str, Any]:
        """Normalize possible wrapper response shapes to an item payload."""
        if not isinstance(response, dict):
            return {}

        wrapped = response.get("item")
        if isinstance(wrapped, dict):
            return wrapped

        wrapped_data = response.get("data")
        if isinstance(wrapped_data, dict):
            return wrapped_data

        return response

    def query_all_items(
        self,
        q: str | None = None,
        page: int | None = None,
        pageSize: int | None = None,
        tags: list[str] | None = None,
        labels: list[str] | None = None,
        locations: list[str] | None = None,
        parentIds: list[str] | None = None,
    ) -> PaginationResultRepoItemSummary:
        """Search and paginate all items in the group.

        Args:
            q: Free-text search string.
            page: Page number (1-based).
            pageSize: Number of items per page.
            tags: Filter to items that carry any of the given tag IDs.
            labels: Backward-compatible alias for ``tags``.
            locations: Filter to items stored at any of the given location IDs.
            parentIds: Filter to items that are children of the given item IDs.

        Returns:
            PaginationResultRepoItemSummary: Paginated list of matching item
                summaries together with total count and pagination metadata.
        """
        params = {}
        if q:
            params["q"] = q
        if page:
            params["page"] = page
        if pageSize:
            params["pageSize"] = pageSize
        tag_filters = tags if tags is not None else labels
        if tag_filters:
            params["tags"] = tag_filters
        if locations:
            params["locations"] = locations
        if parentIds:
            params["parentIds"] = parentIds
        return PaginationResultRepoItemSummary(**self.client._request("get", "/v1/items", params=params))

    def create_item(self, data: ItemCreate) -> ItemSummary:
        """Create a new item.

        Args:
            data: Item creation payload.  ``name`` is required; ``locationId``,
                ``labelIds``, ``description``, ``quantity``, and ``parentId`` are
                optional.

        Returns:
            ItemSummary: Summary representation of the newly created item.
        """
        payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
        return ItemSummary(**self.client._request("post", "/v1/items", data=payload))

    def export_items(self) -> str:
        """Export all items as a CSV document.

        Returns:
            str: Raw CSV text that can be written to a file or parsed directly.
        """
        return self.client._get("/v1/items/export", binary=False)

    def get_all_custom_field_names(self) -> list[str]:
        """Return the distinct custom field names used across all items.

        Returns:
            list[str]: Sorted list of custom field name strings.
        """
        rest = self.client._request("get", "/v1/items/fields")
        return rest.get("data", [])

    def get_all_custom_field_values(self) -> list[str]:
        """Return the distinct values stored in custom text fields across all items.

        Returns:
            list[str]: List of unique custom field value strings.
        """
        rest = self.client._request("get", "/v1/items/fields/values")
        return rest.get("data", [])

    def import_items(self, csv: bytes):
        """Import items from a CSV file.

        The CSV format matches the one produced by :meth:`export_items`.

        Args:
            csv: Raw CSV bytes to upload (e.g. the contents of an exported
                file opened in binary mode).
        """
        files = {"csv": ("items.csv", csv, "text/csv")}
        self.client._request("post", "/v1/items/import", files=files)

    def get_item(self, id: str) -> ItemOut:
        """Return the full details of a single item.

        Args:
            id: UUID of the item.

        Returns:
            ItemOut: Full item representation including attachments, custom
                fields, maintenance log, and nested location/label information.
        """
        response = self.client._request("get", f"/v1/items/{id}")
        return ItemOut(**self._unwrap_item_response(response))

    def update_item(self, id: str, data: ItemUpdate) -> ItemOut:
        """Replace a item's fields with the provided data (full update).

        Args:
            id: UUID of the item to update.
            data: Complete item update payload.  ``name`` is required; all
                other fields are optional.

        Returns:
            ItemOut: Updated full item representation.
        """
        payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
        response = self.client._request("put", f"/v1/items/{id}", data=payload)
        return ItemOut(**self._unwrap_item_response(response))

    def delete_item(self, id: str):
        """Permanently delete an item and its attachments.

        Args:
            id: UUID of the item to delete.
        """
        self.client._request("delete", f"/v1/items/{id}")

    def patch_item(self, id: str, data: ItemPatch) -> ItemOut:
        """Partially update an item (only the provided fields are changed).

        Args:
            id: UUID of the item to patch.
            data: Partial update payload (location, labels, or quantity).

        Returns:
            ItemOut: Updated full item representation.
        """
        payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
        response = self.client._request("patch", f"/v1/items/{id}", data=payload)
        return ItemOut(**self._unwrap_item_response(response))

    def create_item_attachment(
        self,
        id: str,
        file: bytes,
        type: str | None = None,
        primary: bool | None = None,
        name: str | None = None,
    ) -> ItemOut:
        """Upload a file attachment for an item.

        Args:
            id: UUID of the item to attach the file to.
            file: Raw bytes of the file to upload.
            type: Attachment type (e.g. ``"photo"``, ``"manual"``,
                ``"warranty"``, ``"receipt"``).
            primary: When ``True`` this attachment becomes the item's primary
                image.
            name: Display name / title for the attachment.

        Returns:
            ItemOut: Updated full item representation including the new
                attachment.
        """
        files = {"file": (name or "attachment", file)}
        data = {}
        if type:
            data["type"] = type
        if primary:
            data["primary"] = primary
        if name:
            data["name"] = name
        response = self.client._request("post", f"/v1/items/{id}/attachments", data=data, files=files)
        return ItemOut(**self._unwrap_item_response(response))

    def get_item_attachment(self, id: str, attachment_id: str) -> bytes:
        """Retrieve a short-lived download token for an item attachment.

        Args:
            id: UUID of the item.
            attachment_id: UUID of the attachment.

        Returns:
            bytes: Raw bytes of the attachment.
        """
        return self.client._get(f"/v1/items/{id}/attachments/{attachment_id}", binary=True)

    def update_item_attachment(self, id: str, attachment_id: str, data: ItemAttachmentUpdate) -> ItemOut:
        """Update metadata for an existing item attachment.

        Args:
            id: UUID of the item.
            attachment_id: UUID of the attachment to update.
            data: Fields to update (title, type, and/or primary flag).

        Returns:
            ItemOut: Updated full item representation.
        """
        response = self.client._request("put", f"/v1/items/{id}/attachments/{attachment_id}", data=data.model_dump())
        payload = self._unwrap_item_response(response)

        # v24-compatible fallback: if update endpoint doesn't return the item,
        # fetch the latest item state so the method remains ItemOut-compatible.
        if not any(key in payload for key in ("id", "name", "tags", "location", "attachments")):
            return self.get_item(id)

        return ItemOut(**payload)

    def delete_item_attachment(self, id: str, attachment_id: str):
        """Delete an attachment from an item.

        Args:
            id: UUID of the item.
            attachment_id: UUID of the attachment to delete.
        """
        self.client._request("delete", f"/v1/items/{id}/attachments/{attachment_id}")

    def duplicate_item(self, id: str, data: DuplicateOptions) -> ItemOut:
        """Create a duplicate of an existing item.

        Args:
            id: UUID of the item to duplicate.
            data: Options controlling which parts to copy (attachments, custom
                fields, maintenance log) and an optional name prefix.

        Returns:
            ItemOut: Full representation of the newly created duplicate item.
        """
        response = self.client._request("post", f"/v1/items/{id}/duplicate", data=data.model_dump())
        return ItemOut(**self._unwrap_item_response(response))

    def get_maintenance_log(
        self, id: str, status: MaintenanceFilterStatus | None = None
    ) -> list[MaintenanceEntryWithDetails]:
        """Return the maintenance log for a specific item.

        Args:
            id: UUID of the item.
            status: Optional filter – ``"scheduled"``, ``"completed"``, or
                ``"both"`` (default when omitted).

        Returns:
            list[MaintenanceEntryWithDetails]: Maintenance entries with item
                context information attached.
        """
        params = {}
        if status:
            params["status"] = status.value
        data = self.client._request("get", f"/v1/items/{id}/maintenance", params=params)
        return [MaintenanceEntryWithDetails(**item) for item in data.get("data", [])]

    def create_maintenance_entry(self, id: str, data: MaintenanceEntryCreate) -> MaintenanceEntry:
        """Add a maintenance log entry to an item.

        Args:
            id: UUID of the item.
            data: Maintenance entry data.  ``name`` is required; ``description``,
                ``cost``, ``scheduledDate``, and ``completedDate`` are optional.

        Returns:
            MaintenanceEntry: The newly created maintenance entry.
        """
        return MaintenanceEntry(**self.client._request("post", f"/v1/items/{id}/maintenance", data=data.model_dump()))

    def get_item_path(self, id: str) -> list[ItemPath]:
        """Return the ancestry path of an item (from root to the item itself).

        Useful for building breadcrumb navigation in applications.

        Args:
            id: UUID of the item.

        Returns:
            list[ItemPath]: Ordered list of path nodes.  Each node carries an
                ``id``, ``name``, and ``type`` (``"location"`` or ``"item"``).
        """
        data = self.client._request("get", f"/v1/items/{id}/path")
        return [ItemPath(**item) for item in data.get("data", [])]

__init__

__init__(client: HomeboxClient)

Initialise the items sub-client with the shared root client.

Source code in homebox/client.py
def __init__(self, client: HomeboxClient):
    """Initialise the items sub-client with the shared root client."""
    self.client = client

query_all_items

query_all_items(q: str | None = None, page: int | None = None, pageSize: int | None = None, tags: list[str] | None = None, labels: list[str] | None = None, locations: list[str] | None = None, parentIds: list[str] | None = None) -> PaginationResultRepoItemSummary

Search and paginate all items in the group.

Parameters:

Name Type Description Default
q str | None

Free-text search string.

None
page int | None

Page number (1-based).

None
pageSize int | None

Number of items per page.

None
tags list[str] | None

Filter to items that carry any of the given tag IDs.

None
labels list[str] | None

Backward-compatible alias for tags.

None
locations list[str] | None

Filter to items stored at any of the given location IDs.

None
parentIds list[str] | None

Filter to items that are children of the given item IDs.

None

Returns:

Name Type Description
PaginationResultRepoItemSummary PaginationResultRepoItemSummary

Paginated list of matching item summaries together with total count and pagination metadata.

Source code in homebox/client.py
def query_all_items(
    self,
    q: str | None = None,
    page: int | None = None,
    pageSize: int | None = None,
    tags: list[str] | None = None,
    labels: list[str] | None = None,
    locations: list[str] | None = None,
    parentIds: list[str] | None = None,
) -> PaginationResultRepoItemSummary:
    """Search and paginate all items in the group.

    Args:
        q: Free-text search string.
        page: Page number (1-based).
        pageSize: Number of items per page.
        tags: Filter to items that carry any of the given tag IDs.
        labels: Backward-compatible alias for ``tags``.
        locations: Filter to items stored at any of the given location IDs.
        parentIds: Filter to items that are children of the given item IDs.

    Returns:
        PaginationResultRepoItemSummary: Paginated list of matching item
            summaries together with total count and pagination metadata.
    """
    params = {}
    if q:
        params["q"] = q
    if page:
        params["page"] = page
    if pageSize:
        params["pageSize"] = pageSize
    tag_filters = tags if tags is not None else labels
    if tag_filters:
        params["tags"] = tag_filters
    if locations:
        params["locations"] = locations
    if parentIds:
        params["parentIds"] = parentIds
    return PaginationResultRepoItemSummary(**self.client._request("get", "/v1/items", params=params))

create_item

create_item(data: ItemCreate) -> ItemSummary

Create a new item.

Parameters:

Name Type Description Default
data ItemCreate

Item creation payload. name is required; locationId, labelIds, description, quantity, and parentId are optional.

required

Returns:

Name Type Description
ItemSummary ItemSummary

Summary representation of the newly created item.

Source code in homebox/client.py
def create_item(self, data: ItemCreate) -> ItemSummary:
    """Create a new item.

    Args:
        data: Item creation payload.  ``name`` is required; ``locationId``,
            ``labelIds``, ``description``, ``quantity``, and ``parentId`` are
            optional.

    Returns:
        ItemSummary: Summary representation of the newly created item.
    """
    payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
    return ItemSummary(**self.client._request("post", "/v1/items", data=payload))

export_items

export_items() -> str

Export all items as a CSV document.

Returns:

Name Type Description
str str

Raw CSV text that can be written to a file or parsed directly.

Source code in homebox/client.py
def export_items(self) -> str:
    """Export all items as a CSV document.

    Returns:
        str: Raw CSV text that can be written to a file or parsed directly.
    """
    return self.client._get("/v1/items/export", binary=False)

get_all_custom_field_names

get_all_custom_field_names() -> list[str]

Return the distinct custom field names used across all items.

Returns:

Type Description
list[str]

list[str]: Sorted list of custom field name strings.

Source code in homebox/client.py
def get_all_custom_field_names(self) -> list[str]:
    """Return the distinct custom field names used across all items.

    Returns:
        list[str]: Sorted list of custom field name strings.
    """
    rest = self.client._request("get", "/v1/items/fields")
    return rest.get("data", [])

get_all_custom_field_values

get_all_custom_field_values() -> list[str]

Return the distinct values stored in custom text fields across all items.

Returns:

Type Description
list[str]

list[str]: List of unique custom field value strings.

Source code in homebox/client.py
def get_all_custom_field_values(self) -> list[str]:
    """Return the distinct values stored in custom text fields across all items.

    Returns:
        list[str]: List of unique custom field value strings.
    """
    rest = self.client._request("get", "/v1/items/fields/values")
    return rest.get("data", [])

import_items

import_items(csv: bytes)

Import items from a CSV file.

The CSV format matches the one produced by :meth:export_items.

Parameters:

Name Type Description Default
csv bytes

Raw CSV bytes to upload (e.g. the contents of an exported file opened in binary mode).

required
Source code in homebox/client.py
def import_items(self, csv: bytes):
    """Import items from a CSV file.

    The CSV format matches the one produced by :meth:`export_items`.

    Args:
        csv: Raw CSV bytes to upload (e.g. the contents of an exported
            file opened in binary mode).
    """
    files = {"csv": ("items.csv", csv, "text/csv")}
    self.client._request("post", "/v1/items/import", files=files)

get_item

get_item(id: str) -> ItemOut

Return the full details of a single item.

Parameters:

Name Type Description Default
id str

UUID of the item.

required

Returns:

Name Type Description
ItemOut ItemOut

Full item representation including attachments, custom fields, maintenance log, and nested location/label information.

Source code in homebox/client.py
def get_item(self, id: str) -> ItemOut:
    """Return the full details of a single item.

    Args:
        id: UUID of the item.

    Returns:
        ItemOut: Full item representation including attachments, custom
            fields, maintenance log, and nested location/label information.
    """
    response = self.client._request("get", f"/v1/items/{id}")
    return ItemOut(**self._unwrap_item_response(response))

update_item

update_item(id: str, data: ItemUpdate) -> ItemOut

Replace a item's fields with the provided data (full update).

Parameters:

Name Type Description Default
id str

UUID of the item to update.

required
data ItemUpdate

Complete item update payload. name is required; all other fields are optional.

required

Returns:

Name Type Description
ItemOut ItemOut

Updated full item representation.

Source code in homebox/client.py
def update_item(self, id: str, data: ItemUpdate) -> ItemOut:
    """Replace a item's fields with the provided data (full update).

    Args:
        id: UUID of the item to update.
        data: Complete item update payload.  ``name`` is required; all
            other fields are optional.

    Returns:
        ItemOut: Updated full item representation.
    """
    payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
    response = self.client._request("put", f"/v1/items/{id}", data=payload)
    return ItemOut(**self._unwrap_item_response(response))

delete_item

delete_item(id: str)

Permanently delete an item and its attachments.

Parameters:

Name Type Description Default
id str

UUID of the item to delete.

required
Source code in homebox/client.py
def delete_item(self, id: str):
    """Permanently delete an item and its attachments.

    Args:
        id: UUID of the item to delete.
    """
    self.client._request("delete", f"/v1/items/{id}")

patch_item

patch_item(id: str, data: ItemPatch) -> ItemOut

Partially update an item (only the provided fields are changed).

Parameters:

Name Type Description Default
id str

UUID of the item to patch.

required
data ItemPatch

Partial update payload (location, labels, or quantity).

required

Returns:

Name Type Description
ItemOut ItemOut

Updated full item representation.

Source code in homebox/client.py
def patch_item(self, id: str, data: ItemPatch) -> ItemOut:
    """Partially update an item (only the provided fields are changed).

    Args:
        id: UUID of the item to patch.
        data: Partial update payload (location, labels, or quantity).

    Returns:
        ItemOut: Updated full item representation.
    """
    payload = self._normalize_tag_payload(data.model_dump(exclude_none=True))
    response = self.client._request("patch", f"/v1/items/{id}", data=payload)
    return ItemOut(**self._unwrap_item_response(response))

create_item_attachment

create_item_attachment(id: str, file: bytes, type: str | None = None, primary: bool | None = None, name: str | None = None) -> ItemOut

Upload a file attachment for an item.

Parameters:

Name Type Description Default
id str

UUID of the item to attach the file to.

required
file bytes

Raw bytes of the file to upload.

required
type str | None

Attachment type (e.g. "photo", "manual", "warranty", "receipt").

None
primary bool | None

When True this attachment becomes the item's primary image.

None
name str | None

Display name / title for the attachment.

None

Returns:

Name Type Description
ItemOut ItemOut

Updated full item representation including the new attachment.

Source code in homebox/client.py
def create_item_attachment(
    self,
    id: str,
    file: bytes,
    type: str | None = None,
    primary: bool | None = None,
    name: str | None = None,
) -> ItemOut:
    """Upload a file attachment for an item.

    Args:
        id: UUID of the item to attach the file to.
        file: Raw bytes of the file to upload.
        type: Attachment type (e.g. ``"photo"``, ``"manual"``,
            ``"warranty"``, ``"receipt"``).
        primary: When ``True`` this attachment becomes the item's primary
            image.
        name: Display name / title for the attachment.

    Returns:
        ItemOut: Updated full item representation including the new
            attachment.
    """
    files = {"file": (name or "attachment", file)}
    data = {}
    if type:
        data["type"] = type
    if primary:
        data["primary"] = primary
    if name:
        data["name"] = name
    response = self.client._request("post", f"/v1/items/{id}/attachments", data=data, files=files)
    return ItemOut(**self._unwrap_item_response(response))

get_item_attachment

get_item_attachment(id: str, attachment_id: str) -> bytes

Retrieve a short-lived download token for an item attachment.

Parameters:

Name Type Description Default
id str

UUID of the item.

required
attachment_id str

UUID of the attachment.

required

Returns:

Name Type Description
bytes bytes

Raw bytes of the attachment.

Source code in homebox/client.py
def get_item_attachment(self, id: str, attachment_id: str) -> bytes:
    """Retrieve a short-lived download token for an item attachment.

    Args:
        id: UUID of the item.
        attachment_id: UUID of the attachment.

    Returns:
        bytes: Raw bytes of the attachment.
    """
    return self.client._get(f"/v1/items/{id}/attachments/{attachment_id}", binary=True)

update_item_attachment

update_item_attachment(id: str, attachment_id: str, data: ItemAttachmentUpdate) -> ItemOut

Update metadata for an existing item attachment.

Parameters:

Name Type Description Default
id str

UUID of the item.

required
attachment_id str

UUID of the attachment to update.

required
data ItemAttachmentUpdate

Fields to update (title, type, and/or primary flag).

required

Returns:

Name Type Description
ItemOut ItemOut

Updated full item representation.

Source code in homebox/client.py
def update_item_attachment(self, id: str, attachment_id: str, data: ItemAttachmentUpdate) -> ItemOut:
    """Update metadata for an existing item attachment.

    Args:
        id: UUID of the item.
        attachment_id: UUID of the attachment to update.
        data: Fields to update (title, type, and/or primary flag).

    Returns:
        ItemOut: Updated full item representation.
    """
    response = self.client._request("put", f"/v1/items/{id}/attachments/{attachment_id}", data=data.model_dump())
    payload = self._unwrap_item_response(response)

    # v24-compatible fallback: if update endpoint doesn't return the item,
    # fetch the latest item state so the method remains ItemOut-compatible.
    if not any(key in payload for key in ("id", "name", "tags", "location", "attachments")):
        return self.get_item(id)

    return ItemOut(**payload)

delete_item_attachment

delete_item_attachment(id: str, attachment_id: str)

Delete an attachment from an item.

Parameters:

Name Type Description Default
id str

UUID of the item.

required
attachment_id str

UUID of the attachment to delete.

required
Source code in homebox/client.py
def delete_item_attachment(self, id: str, attachment_id: str):
    """Delete an attachment from an item.

    Args:
        id: UUID of the item.
        attachment_id: UUID of the attachment to delete.
    """
    self.client._request("delete", f"/v1/items/{id}/attachments/{attachment_id}")

duplicate_item

duplicate_item(id: str, data: DuplicateOptions) -> ItemOut

Create a duplicate of an existing item.

Parameters:

Name Type Description Default
id str

UUID of the item to duplicate.

required
data DuplicateOptions

Options controlling which parts to copy (attachments, custom fields, maintenance log) and an optional name prefix.

required

Returns:

Name Type Description
ItemOut ItemOut

Full representation of the newly created duplicate item.

Source code in homebox/client.py
def duplicate_item(self, id: str, data: DuplicateOptions) -> ItemOut:
    """Create a duplicate of an existing item.

    Args:
        id: UUID of the item to duplicate.
        data: Options controlling which parts to copy (attachments, custom
            fields, maintenance log) and an optional name prefix.

    Returns:
        ItemOut: Full representation of the newly created duplicate item.
    """
    response = self.client._request("post", f"/v1/items/{id}/duplicate", data=data.model_dump())
    return ItemOut(**self._unwrap_item_response(response))

get_maintenance_log

get_maintenance_log(id: str, status: MaintenanceFilterStatus | None = None) -> list[MaintenanceEntryWithDetails]

Return the maintenance log for a specific item.

Parameters:

Name Type Description Default
id str

UUID of the item.

required
status MaintenanceFilterStatus | None

Optional filter – "scheduled", "completed", or "both" (default when omitted).

None

Returns:

Type Description
list[MaintenanceEntryWithDetails]

list[MaintenanceEntryWithDetails]: Maintenance entries with item context information attached.

Source code in homebox/client.py
def get_maintenance_log(
    self, id: str, status: MaintenanceFilterStatus | None = None
) -> list[MaintenanceEntryWithDetails]:
    """Return the maintenance log for a specific item.

    Args:
        id: UUID of the item.
        status: Optional filter – ``"scheduled"``, ``"completed"``, or
            ``"both"`` (default when omitted).

    Returns:
        list[MaintenanceEntryWithDetails]: Maintenance entries with item
            context information attached.
    """
    params = {}
    if status:
        params["status"] = status.value
    data = self.client._request("get", f"/v1/items/{id}/maintenance", params=params)
    return [MaintenanceEntryWithDetails(**item) for item in data.get("data", [])]

create_maintenance_entry

create_maintenance_entry(id: str, data: MaintenanceEntryCreate) -> MaintenanceEntry

Add a maintenance log entry to an item.

Parameters:

Name Type Description Default
id str

UUID of the item.

required
data MaintenanceEntryCreate

Maintenance entry data. name is required; description, cost, scheduledDate, and completedDate are optional.

required

Returns:

Name Type Description
MaintenanceEntry MaintenanceEntry

The newly created maintenance entry.

Source code in homebox/client.py
def create_maintenance_entry(self, id: str, data: MaintenanceEntryCreate) -> MaintenanceEntry:
    """Add a maintenance log entry to an item.

    Args:
        id: UUID of the item.
        data: Maintenance entry data.  ``name`` is required; ``description``,
            ``cost``, ``scheduledDate``, and ``completedDate`` are optional.

    Returns:
        MaintenanceEntry: The newly created maintenance entry.
    """
    return MaintenanceEntry(**self.client._request("post", f"/v1/items/{id}/maintenance", data=data.model_dump()))

get_item_path

get_item_path(id: str) -> list[ItemPath]

Return the ancestry path of an item (from root to the item itself).

Useful for building breadcrumb navigation in applications.

Parameters:

Name Type Description Default
id str

UUID of the item.

required

Returns:

Type Description
list[ItemPath]

list[ItemPath]: Ordered list of path nodes. Each node carries an id, name, and type ("location" or "item").

Source code in homebox/client.py
def get_item_path(self, id: str) -> list[ItemPath]:
    """Return the ancestry path of an item (from root to the item itself).

    Useful for building breadcrumb navigation in applications.

    Args:
        id: UUID of the item.

    Returns:
        list[ItemPath]: Ordered list of path nodes.  Each node carries an
            ``id``, ``name``, and ``type`` (``"location"`` or ``"item"``).
    """
    data = self.client._request("get", f"/v1/items/{id}/path")
    return [ItemPath(**item) for item in data.get("data", [])]