Items
Manage freezer items within a household. Items support full-text search, filtering, pagination, soft-delete with an archive, and change history tracking. All endpoints are prefixed with /api/v1/households/:hid/items.
FreezerItemResponse
All item endpoints return objects with this shape:
{
"id" : "clh7h9i0j0008qw08x5y6z7a8" ,
"householdId" : "clh3a1b2c0001qw08k5m7n9p0" ,
"freezerId" : "clh5e6f7g0005qw08l2m3n4o5" ,
"compartmentId" : "clh6f7g8h0006qw08p3q4r5s6" ,
"name" : "Chicken breast" ,
"quantity" : 4 ,
"notes" : "Bought from Costco" ,
"storedAt" : "2025-01-15T10:30:00.000Z" ,
"expiresAt" : "2025-07-15T00:00:00.000Z" ,
"deletedAt" : null ,
"createdAt" : "2025-01-15T10:30:00.000Z" ,
"updatedAt" : "2025-01-15T10:30:00.000Z" ,
"createdBy" : {
"id" : "clh2v3x0k0000qw08z1y9d3rk" ,
"email" : "jane@example.com" ,
"name" : "Jane Doe"
},
"updatedBy" : {
"id" : "clh2v3x0k0000qw08z1y9d3rk" ,
"email" : "jane@example.com" ,
"name" : "Jane Doe"
}
}
Field
Type
Description
id
string
Item ID (CUID2)
householdId
string
Parent household ID
freezerId
string
Freezer the item is stored in
compartmentId
string
Compartment within the freezer
name
string
Item name
quantity
number
Number of units
notes
string \| null
Optional notes
storedAt
string \| null
When the item was placed in the freezer
expiresAt
string \| null
Expiration date
deletedAt
string \| null
Soft-delete timestamp (null if active)
createdAt
string
Record creation timestamp
updatedAt
string
Last update timestamp
createdBy
UserResponse
User who created the item
updatedBy
UserResponse
User who last updated the item
POST /households/:hid/items
Create a new freezer item.
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
Request body
{
"name" : "Chicken breast" ,
"quantity" : 4 ,
"freezerId" : "clh5e6f7g0005qw08l2m3n4o5" ,
"compartmentId" : "clh6f7g8h0006qw08p3q4r5s6" ,
"notes" : "Bought from Costco" ,
"storedAt" : "2025-01-15T10:30:00.000Z" ,
"expiresAt" : "2025-07-15T00:00:00.000Z"
}
Field
Type
Required
Description
name
string
Yes
Item name
quantity
number
Yes
Number of units
freezerId
string
Yes
Target freezer ID
compartmentId
string
Yes
Target compartment ID
notes
string
No
Optional notes
storedAt
string
No
ISO-8601 date when stored (defaults to now)
expiresAt
string
No
ISO-8601 expiration date
Response 201 Created
Returns the full FreezerItemResponse.
Example
curl -X POST http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>" \
-d '{
"name": "Chicken breast",
"quantity": 4,
"freezerId": "clh5e6f7g0005qw08l2m3n4o5",
"compartmentId": "clh6f7g8h0006qw08p3q4r5s6",
"notes": "Bought from Costco",
"expiresAt": "2025-07-15T00:00:00.000Z"
}'
GET /households/:hid/items
List active items with optional filtering and pagination.
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
Query parameters
Param
Type
Default
Description
freezerId
string
--
Filter by freezer
compartmentIds[]
string[]
--
Filter by one or more compartments
search
string
--
Full-text search on item name
expiresBefore
string
--
ISO-8601 date; return items expiring before this date
page
number
1
Page number (1-indexed)
limit
number
20
Items per page
Response 200 OK
Returns a PaginatedResponse<FreezerItemResponse>.
{
"data" : [
{
"id" : "clh7h9i0j0008qw08x5y6z7a8" ,
"name" : "Chicken breast" ,
"quantity" : 4 ,
"freezerId" : "clh5e6f7g0005qw08l2m3n4o5" ,
"compartmentId" : "clh6f7g8h0006qw08p3q4r5s6" ,
"storedAt" : "2025-01-15T10:30:00.000Z" ,
"expiresAt" : "2025-07-15T00:00:00.000Z" ,
"deletedAt" : null ,
"createdAt" : "2025-01-15T10:30:00.000Z" ,
"updatedAt" : "2025-01-15T10:30:00.000Z" ,
"createdBy" : { "id" : "clh2v3x0k0000qw08z1y9d3rk" , "email" : "jane@example.com" , "name" : "Jane Doe" },
"updatedBy" : { "id" : "clh2v3x0k0000qw08z1y9d3rk" , "email" : "jane@example.com" , "name" : "Jane Doe" },
"householdId" : "clh3a1b2c0001qw08k5m7n9p0" ,
"notes" : "Bought from Costco"
}
],
"total" : 42 ,
"page" : 1 ,
"limit" : 20
}
Examples
# List all items (first page)
curl "http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items" \
-H "Authorization: Bearer <accessToken>"
# Filter by freezer and search
curl "http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items?freezerId=clh5e6f7g0005qw08l2m3n4o5&search=chicken" \
-H "Authorization: Bearer <accessToken>"
# Find items expiring before a date, page 2
curl "http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items?expiresBefore=2025-03-01T00:00:00.000Z&page=2&limit=10" \
-H "Authorization: Bearer <accessToken>"
# Filter by multiple compartments
curl "http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items?compartmentIds[]=clh6f7g8h0006qw08p3q4r5s6&compartmentIds[]=clh6g8h9i0007qw08t4u5v6w7" \
-H "Authorization: Bearer <accessToken>"
GET /households/:hid/items/archive
List soft-deleted items (items with a non-null deletedAt).
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
Response 200 OK
Returns an array of FreezerItemResponse where deletedAt is set.
[
{
"id" : "clh7h9i0j0008qw08x5y6z7a8" ,
"name" : "Expired salmon" ,
"quantity" : 1 ,
"deletedAt" : "2025-02-01T12:00:00.000Z" ,
"..."
}
]
Example
curl http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/archive \
-H "Authorization: Bearer <accessToken>"
GET /households/:hid/items/:iid
Get a single item by ID.
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
iid
string
Item ID (CUID2)
Response 200 OK
Returns the full FreezerItemResponse.
Example
curl http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/clh7h9i0j0008qw08x5y6z7a8 \
-H "Authorization: Bearer <accessToken>"
PATCH /households/:hid/items/:iid
Update an item. Each changed field creates a change log entry (see GET /:iid/history ).
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
iid
string
Item ID (CUID2)
Request body
Any subset of the create-item fields:
{
"name" : "Chicken thighs" ,
"quantity" : 6 ,
"compartmentId" : "clh6g8h9i0007qw08t4u5v6w7" ,
"notes" : "Moved to bottom drawer"
}
Field
Type
Required
name
string
No
quantity
number
No
freezerId
string
No
compartmentId
string
No
notes
string
No
storedAt
string
No
expiresAt
string
No
Response 200 OK
Returns the updated FreezerItemResponse.
Example
curl -X PATCH http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/clh7h9i0j0008qw08x5y6z7a8 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>" \
-d '{
"quantity": 2,
"notes": "Used 2 for dinner"
}'
DELETE /households/:hid/items/:iid
Soft-delete an item by setting deletedAt to the current timestamp. The item moves to the archive.
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
iid
string
Item ID (CUID2)
Response 200 OK
{
"message" : "Item archived successfully"
}
Example
curl -X DELETE http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/clh7h9i0j0008qw08x5y6z7a8 \
-H "Authorization: Bearer <accessToken>"
DELETE /households/:hid/items/:iid/permanent
Permanently delete an item from the archive. The item must have been soft-deleted first.
Auth
HouseholdOwnerGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
iid
string
Item ID (CUID2)
Response 200 OK
{
"message" : "Item permanently deleted"
}
Errors
Status
Reason
400
Item is not in the archive (must be soft-deleted first)
Example
curl -X DELETE http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/clh7h9i0j0008qw08x5y6z7a8/permanent \
-H "Authorization: Bearer <accessToken>"
GET /households/:hid/items/:iid/history
Retrieve the change log for an item. Each entry records a single field change with old and new values.
Auth
HouseholdMemberGuard
Rate limit
100 req/min
Path parameters
Param
Type
Description
hid
string
Household ID (CUID2)
iid
string
Item ID (CUID2)
Response 200 OK
Returns an array of ChangeLogEntryResponse:
[
{
"id" : "clh8i0j1k0009qw08b6c7d8e9" ,
"itemId" : "clh7h9i0j0008qw08x5y6z7a8" ,
"fieldName" : "quantity" ,
"oldValue" : "4" ,
"newValue" : "2" ,
"changedAt" : "2025-01-20T14:00:00.000Z" ,
"changedBy" : {
"id" : "clh2v3x0k0000qw08z1y9d3rk" ,
"email" : "jane@example.com" ,
"name" : "Jane Doe"
}
},
{
"id" : "clh8j1k2l0010qw08f7g8h9i0" ,
"itemId" : "clh7h9i0j0008qw08x5y6z7a8" ,
"fieldName" : "notes" ,
"oldValue" : "Bought from Costco" ,
"newValue" : "Used 2 for dinner" ,
"changedAt" : "2025-01-20T14:00:00.000Z" ,
"changedBy" : {
"id" : "clh2v3x0k0000qw08z1y9d3rk" ,
"email" : "jane@example.com" ,
"name" : "Jane Doe"
}
}
]
Field
Type
Description
id
string
Change log entry ID (CUID2)
itemId
string
Item that was changed
fieldName
string
Name of the changed field
oldValue
string \| null
Previous value (stringified)
newValue
string \| null
New value (stringified)
changedAt
string
ISO-8601 timestamp of the change
changedBy
UserResponse
User who made the change
Example
curl http://localhost:3000/api/v1/households/clh3a1b2c0001qw08k5m7n9p0/items/clh7h9i0j0008qw08x5y6z7a8/history \
-H "Authorization: Bearer <accessToken>"