Skip to content

Entity Merge Upgrade Guide

This guide covers the breaking changes introduced by the entity merge — the unification of the items and locations tables into a single entities table. This is primarily relevant to developers integrating with the Homebox API.

The items and locations database tables have been merged into a single entities table. All related tables have been renamed accordingly. A new entity_types table has been introduced to differentiate between items and locations using a user-definable type system.

Old TableNew Table
itemsentities
locationsmerged into entities
item_fieldsentity_fields
item_templatesentity_templates
tag_itemstag_entities

Key column renames:

Old ColumnNew Column
group_items / group_locationsgroup_entities
item_children / location_childrenentity_children
location_itemsremoved (absorbed into entity_children)
item_attachmentsentity_attachments
item_id (maintenance_entries)entity_id
sync_child_items_locationssync_child_entity_locations

The migration runs automatically on startup. It:

  1. Creates the entity_types table and seeds default “Item” and “Location” types per group
  2. Renames the items table to entities and renames all columns
  3. Inserts all locations into entities preserving their original UUIDs
  4. Re-parents items under their former locations using the unified entity_children column
  5. Renames all related tables and their foreign key columns
  6. Drops the locations table
  7. Assigns asset IDs to any entities that don’t have them (including former locations)

All /v1/items/* and /v1/locations/* endpoints have been removed. They are replaced by the unified /v1/entities/* endpoints.

Entities (replaces both Items and Locations)

Section titled “Entities (replaces both Items and Locations)”
MethodPathDescription
GET/v1/entitiesQuery entities (items by default, locations with ?isLocation=true)
POST/v1/entitiesCreate an entity (item or location based on entityTypeId)
GET/v1/entities/treeGet the location/item tree
GET/v1/entities/exportExport entities as CSV
POST/v1/entities/importImport entities from CSV
GET/v1/entities/fieldsGet all custom field names
GET/v1/entities/fields/valuesGet all values for a custom field
GET/v1/entities/{id}Get a single entity
GET/v1/entities/{id}/pathGet the full path to an entity
PUT/v1/entities/{id}Update an entity
PATCH/v1/entities/{id}Partial update an entity
DELETE/v1/entities/{id}Delete an entity
POST/v1/entities/{id}/duplicateDuplicate an entity
POST/v1/entities/{id}/attachmentsAdd an attachment
PUT/v1/entities/{id}/attachments/{attachment_id}Update an attachment
DELETE/v1/entities/{id}/attachments/{attachment_id}Delete an attachment
GET/v1/entities/{id}/attachments/{attachment_id}Get an attachment file
GET/v1/entities/{id}/maintenanceGet maintenance log
POST/v1/entities/{id}/maintenanceCreate maintenance entry
MethodPathDescription
GET/v1/entity-typesList all entity types for the group
POST/v1/entity-typesCreate an entity type
PUT/v1/entity-types/{id}Update an entity type
DELETE/v1/entity-types/{id}Delete an entity type
ParameterTypeDescription
isLocationboolFilter by entity type. true = locations only (returns array with itemCount), false = items only. Omit for items only (default).
filterChildrenboolWhen isLocation=true, only return root locations (no parent).
parentIds[]stringFilter entities by parent ID. Replaces the old locations parameter.
qstringSearch query (unchanged)
tags[]stringFilter by tag IDs (unchanged)
page, pageSizeintPagination (unchanged)
orderBystringSort order (unchanged)
includeArchivedboolInclude archived entities (unchanged)
{
"name": "My Item",
"description": "A description",
"quantity": 1,
"parentId": "uuid-of-parent-location",
"entityTypeId": "uuid-of-entity-type",
"tagIds": ["uuid-1", "uuid-2"]
}

Key changes from the old POST /v1/items:

  • locationIdparentId — the parent entity (typically a location)
  • entityTypeId — new optional field. If omitted, defaults to the group’s default “Item” type. To create a location, pass a location-type entity type ID.
  • locationIdparentId
  • syncChildItemsLocationssyncChildEntityLocations
  • entityTypeId — optional, can change the entity’s type

The location field has been replaced by parent:

{
"id": "...",
"name": "My Item",
"parent": {
"id": "...",
"name": "Living Room"
},
"entityType": {
"id": "...",
"name": "Item",
"isLocation": false
},
"tags": [...],
...
}

The children field on an entity now only includes location-type children (sub-containers). Items inside a location are retrieved separately via GET /v1/entities?parentIds=[locationId].

The item.mutation and location.mutation events have been merged into a single entity.mutation event.

{
"event": "entity.mutation",
"data": {
"gid": "group-uuid"
}
}
  1. Replace all /v1/items/* and /v1/locations/* URLs with /v1/entities/*
  2. Replace locationId with parentId in create/update payloads
  3. Replace syncChildItemsLocations with syncChildEntityLocations in update payloads
  4. Replace item.location with item.parent when reading entity responses
  5. Use ?isLocation=true to query locations, ?parentIds= instead of ?locations= to filter by parent
  6. Listen for entity.mutation instead of item.mutation / location.mutation on WebSocket
  7. Use /v1/entity-types to manage and query available entity types