Catalogue items
CRUD endpoints for managing catalogue items.
Catalogue items API
CRUD endpoints for managing catalogue items.
Endpoints
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/catalogue_items |
List catalogue items |
| GET | /api/v1/catalogue_items/{id} |
Show a catalogue item |
| POST | /api/v1/catalogue_items |
Create a catalogue item |
| PUT | /api/v1/catalogue_items/{id} |
Update a catalogue item |
| DELETE | /api/v1/catalogue_items/{id} |
Delete (soft-delete) a catalogue item |
| POST | /api/v1/catalogue_items/{id}/merge |
Merge another catalogue item into this one |
Nested Resources
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/catalogue_items/{id}/accessories |
List accessories |
| POST | /api/v1/catalogue_items/{id}/accessories |
Add an accessory |
| PUT | /api/v1/catalogue_items/{id}/accessories/{accessory_id} |
Update an accessory |
| DELETE | /api/v1/catalogue_items/{id}/accessories/{accessory_id} |
Remove an accessory |
Authentication
Requires a Sanctum bearer token with catalogue-items:read (GET) or catalogue-items:write (POST/PUT/DELETE) ability.
List CatalogueItems
GET /api/v1/catalogue_items
Filters
| Parameter | Description |
|---|---|
q[name_cont]=LED |
Name contains |
q[catalogue_item_type_eq]=rental |
Filter by type |
q[is_active_eq]=true |
Active catalogue items only |
q[catalogue_item_group_id_eq]=5 |
Filter by catalogue item group |
q[sku_cont]=SKU |
SKU contains |
q[barcode_eq]=123456 |
Exact barcode match |
q[catalogue_method_eq]=2 |
Filter by catalogue method |
q[cf.field_name_eq]=value |
Filter by custom field |
Sorts
| Parameter | Description |
|---|---|
sort=name |
Sort by name ascending |
sort=-name |
Sort by name descending |
sort=catalogue_item_type |
Sort by catalogue item type |
sort=sku |
Sort by SKU |
sort=created_at |
Sort by creation date |
Includes
Eager-load relationships with ?include=catalogueItemGroup,taxType,assets,accessories,customFieldValues
Live filters
Apply a saved live filter: ?filter_id=3
View filters merge with explicit q params (explicit params take priority). View sort applies only when no explicit sort param is given.
Response
{
"catalogue_items": [
{
"id": 1,
"name": "LED Wash Light",
"description": "Professional LED wash fixture",
"catalogue_item_type": "rental",
"catalogue_item_group_id": 2,
"product_group_name": "Lighting",
"sku": "LED-WASH-001",
"barcode": "5060001234567",
"is_active": true,
"catalogue_method": 2,
"weight": "5.5000",
"replacement_charge": "500.00",
"custom_fields": {
"power_rating": "150W"
},
"created_at": "2026-01-15T14:30:00Z",
"updated_at": "2026-01-15T14:30:00Z"
}
],
"meta": {
"total": 42,
"per_page": 20,
"page": 1
}
}
Show CatalogueItem
GET /api/v1/catalogue_items/{id}
Response
{
"catalogue_item": {
"id": 1,
"name": "LED Wash Light",
"description": "Professional LED wash fixture",
"catalogue_item_type": "rental",
"catalogue_item_group_id": 2,
"product_group_name": "Lighting",
"sku": "LED-WASH-001",
"barcode": "5060001234567",
"is_active": true,
"catalogue_method": 2,
"preferred_catalogue_type": 1,
"weight": "5.5000",
"replacement_charge": "500.00",
"buffer_percent": "0.00",
"post_rent_unavailability": 0,
"accessory_only": false,
"system": false,
"discountable": true,
"tax_type_id": 1,
"purchase_tax_type_id": null,
"rental_revenue_group_id": 1,
"sale_revenue_group_id": null,
"sub_rental_cost_group_id": null,
"sub_rental_price": "0.00",
"purchase_cost_group_id": null,
"purchase_price": "0.00",
"country_of_origin_id": null,
"tag_list": ["lighting", "led"],
"custom_fields": {},
"created_at": "2026-01-15T14:30:00Z",
"updated_at": "2026-01-15T14:30:00Z"
}
}
Create CatalogueItem
POST /api/v1/catalogue_items
Request Body
{
"name": "Moving Head Spot",
"catalogue_item_type": "rental",
"catalogue_item_group_id": 2,
"sku": "MH-SPOT-001",
"catalogue_method": 2,
"is_active": true
}
Response
Returns 201 Created with the catalogue item object.
Update CatalogueItem
PUT /api/v1/catalogue_items/{id}
Only include fields to update. Omitted fields remain unchanged.
Clearing nullable fields: Omitting a field or sending
nullleaves it unchanged. To clear a nullable field tonull, send an empty string""as its value.
Response
Returns 200 OK with the updated catalogue item object.
Delete CatalogueItem
DELETE /api/v1/catalogue_items/{id}
Soft-deletes the catalogue item. Returns 204 No Content.
Merge CatalogueItem
POST /api/v1/catalogue_items/{id}/merge
Merges a secondary catalogue item into the catalogue item in the URL (the primary). Stock, accessories, custom-field values, and attachments transfer to the primary, and the secondary is soft-deleted. Requires the catalogue-items:write ability.
Request Body
{
"secondary_id": 42
}
The secondary_id must reference an existing, non-archived catalogue item and must differ from the primary. Attempting to merge a catalogue item into itself returns a 422 validation error.
Response
Returns 200 OK with the merged primary catalogue item object.
Kit Components
A catalogue item can be a kit — composed of other catalogue items (its bill-of-materials) rather than tracked as stock directly. Kit components are managed as a sub-resource of the parent catalogue item. Adding the first component flips the catalogue item's is_kit flag to true; removing the last component flips it back to false.
Kit availability is composed read-time from component availability, so the composition must stay acyclic and within the configured nesting depth (availability.kit_nesting_max_depth).
Endpoints
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/catalogue_items/{catalogue_item}/components |
List a catalogue item's kit components |
| POST | /api/v1/catalogue_items/{catalogue_item}/components |
Add a component to the kit |
| PATCH | /api/v1/catalogue_items/{catalogue_item}/components/{component} |
Update a component line |
| DELETE | /api/v1/catalogue_items/{catalogue_item}/components/{component} |
Remove a component |
Authentication
Requires the kits:read ability (GET) or kits:write (POST/PATCH/DELETE), and the matching kits.view / kits.manage permission.
List Components
GET /api/v1/catalogue_items/{catalogue_item}/components
{
"components": [
{
"id": 1,
"catalogue_item_id": 10,
"component_catalogue_item_id": 42,
"component_name": "Par Can 64",
"quantity": "4.0000",
"binding": "pool",
"sort_order": 0
}
]
}
| Field | Type | Description |
|---|---|---|
id |
int | Component line ID |
catalogue_item_id |
int | Parent kit catalogue item ID |
component_catalogue_item_id |
int | Component catalogue item ID |
component_name |
string | Name of the component catalogue item |
quantity |
string | Quantity of the component per single kit (decimal string) |
binding |
string | pool (drawn from general stock) or fixed (permanently flightcase-assigned) |
sort_order |
int | Display order |
Add Component
POST /api/v1/catalogue_items/{catalogue_item}/components
| Field | Type | Required | Description |
|---|---|---|---|
component_catalogue_item_id |
int | Yes | CatalogueItem to add as a component (must exist) |
quantity |
numeric | No | Quantity per kit (min 1, default 1) |
binding |
string | No | pool (default) or fixed |
sort_order |
int | No | Display order (min 0, default 0) |
The catalogue_item_id is taken from the URL. Returns 201 Created with the new component in a component key.
Rejected with 422 when the component is the catalogue item itself, would create a circular composition, would exceed the maximum kit nesting depth, or is already a component of the kit.
Update Component
PATCH /api/v1/catalogue_items/{catalogue_item}/components/{component}
All fields optional (quantity, binding, sort_order); only those supplied change. The parent kit and component catalogue item cannot be re-pointed — remove and re-add instead. A component that does not belong to the catalogue item in the URL returns 404. Returns 200 OK.
Remove Component
DELETE /api/v1/catalogue_items/{catalogue_item}/components/{component}
Removes the component. Returns 204 No Content. Removing the last component flips the catalogue item's is_kit flag back to false.