Cliento API reference: Colour bar

Base URL: https://api.cliento.com

The Colour bar APIs are for hair salons. They let an integration manage a salon's stock of hair colour and keep it correct as the colour is used.

Hair colour is not sold to the customer. It is used a little at a time: a tube is opened, and each mix takes some grams from it. The colour bar keeps track of both the packs in stock and how much is left in the open one.

There are three APIs:

  • Colour bar ranges. A range is a supplier's series, such as one brand's permanent colours.
  • Colour bar items. An item is one shade in a range. Each item has its own stock.
  • Colour bar mixes. A mix is what a staff member mixed for one customer. Registering a mix takes the grams used from each item's stock.

Deliveries are recorded through the Stock movements API.

Colour bar ranges

Industry: hair and beauty. The Colour bar ranges API lets an integration read a salon's ranges and create, change and delete them.

A range is a supplier's series, such as one brand's permanent colours. It has an id of the form cbr_... and belongs to a location. The items of a range share three settings, which are set on the range: kind, packSize and listPrice.

Ranges are under /v1/locations/{locationId}/colour-bar-ranges. A range is also read by its id, without its location, at /v1/colour-bar-ranges/{colourBarRangeId}. Reading needs the scope products:read. Writing needs stock:write.

  • kind is a lower-case word such as colour, bleach or developer. The list is open: send the word that fits.
  • A range without a packSize is one whose items are used a whole pack at a time, such as a treatment. Its items have no open pack, except an item with a packSize of its own.
  • listPrice is the supplier's list price of one pack, VAT excluded. It is what the location values its use of the range's items at, and is not what the location paid.
  • An item can have a packSize and a listPrice of its own. Changing the range's packSize or listPrice changes what applies to every item without a value of its own.
  • A range that still has items cannot be deleted. Delete its items first.

List colour bar ranges

GET /v1/locations/{locationId}/colour-bar-ranges

Scope: products:read

Stability: preview

The location's colour bar ranges by name, one page at a time.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
limitqueryinteger (int32)NoPage size, 1 to 200. Default 50.
afterquerystringNoThe nextCursor of the previous page.

Responses

StatusDescriptionBody
200OKColourBarRangeList
defaultAny failure. See the Errors section.Error

Create a colour bar range

POST /v1/locations/{locationId}/colour-bar-ranges

Scope: stock:write

Stability: preview

Adds a range to the location's colour bar. It holds no items until they are created. Send an Idempotency-Key so that a repeat of the call does not add the range twice.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarRangeCreate

Responses

StatusDescriptionBody
201CreatedColourBarRange
defaultAny failure. See the Errors section.Error

Get a colour bar range

GET /v1/locations/{locationId}/colour-bar-ranges/{colourBarRangeId}

Scope: products:read

Stability: preview

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarRangeIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarRange
defaultAny failure. See the Errors section.Error

Get a colour bar range by id

GET /v1/colour-bar-ranges/{colourBarRangeId}

Scope: products:read

Stability: preview

The same colour bar range as under its location, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries locationId.

Parameters

NameInTypeRequiredDescription
colourBarRangeIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarRange
defaultAny failure. See the Errors section.Error

Update a colour bar range

PATCH /v1/locations/{locationId}/colour-bar-ranges/{colourBarRangeId}

Scope: stock:write

Stability: preview

Changes only the fields in the request. Either all of them are changed or none. See ColourBarRangeUpdate for how to clear a field.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarRangeIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarRangeUpdate

Responses

StatusDescriptionBody
200OKColourBarRange
defaultAny failure. See the Errors section.Error

Delete a colour bar range

DELETE /v1/locations/{locationId}/colour-bar-ranges/{colourBarRangeId}

Scope: stock:write

Stability: preview

Deleting a range that still has items is refused with not_allowed. Delete its items first.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarRangeIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Responses

StatusDescriptionBody
204No Content
defaultAny failure. See the Errors section.Error

Colour bar items

Industry: hair and beauty. The Colour bar items API lets an integration read a salon's colour bar items and create, change and delete them.

An item is one shade in a range. It can also be one strength of a developer or one tub of bleach. It has an id of the form cbi_... and belongs to its range's location.

Each item has its own stock. The stock is counted in packs. The item also keeps how many grams have been taken from the open pack.

An item is not a product. A product is sold at a point of sale and is read through the Products API. An item is used in the salon and is never sold.

Items are under /v1/locations/{locationId}/colour-bar-items. An item is also read by its id, without its location, at /v1/colour-bar-items/{colourBarItemId}. Reading needs the scope products:read. Writing needs stock:write.

  • Stock is counted in packs, and the open pack counts as one. packs is 4 for three unopened tubes and one that is open. openUsed is the grams that have been taken from the open pack, and 0 when none is open.
  • unopenedPacks, openLeft and gramsLeft are worked out from packs, openUsed and the pack size, and are read-only.
  • packs and openUsed are read-only here. A delivery adds packs and a withdrawal takes them: record both through the Stock movements API, on a line with the item's colourBarItemId and the quantity in whole packs. openUsed changes when a colour bar mix is registered, in Cliento or through the Colour bar mixes API.
  • An item follows its range's packSize and listPrice unless it has its own. The item's own values are packSize and listPrice; packSizeInUse and listPriceInUse are what applies.
  • eans holds the item's barcodes. An item made from an article in a supplier's catalogue also has that article's barcodes, which catalogueEans lists. Only the item's own barcodes are added and removed here.
  • To find the item for a scanned barcode or a row of a delivery note, list with ean or articleNumber. Look up the barcode first: a supplier can change its article numbers, and a barcode stays with the pack.
  • A range holds a shade once: a second item with the same shade is refused with duplicate.
  • An item without a name of its own is called by its shade.

List colour bar items

GET /v1/locations/{locationId}/colour-bar-items

Scope: products:read

Stability: preview

The location's colour bar items, range by range and shade by shade, one page at a time. With ean or articleNumber it is a lookup: the item a scanned barcode or a delivery note row belongs to, at most 20 items. Send one of rangeId, ean and articleNumber, or none.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
limitqueryinteger (int32)NoPage size, 1 to 200. Default 50.
afterquerystringNoThe nextCursor of the previous page.
rangeIdquerystringNoOnly the items of this colour bar range.
eanquerystringNoOnly items with this barcode: their own, or that of the supplier's article they were made from.
articleNumberquerystringNoOnly items with exactly this article number.

Responses

StatusDescriptionBody
200OKColourBarItemList
defaultAny failure. See the Errors section.Error

Create a colour bar item

POST /v1/locations/{locationId}/colour-bar-items

Scope: stock:write

Stability: preview

Adds an item to a colour bar range. It starts with no stock. Send an Idempotency-Key so that a repeat of the call does not add the item twice. A shade the range already holds, or a barcode that another item or a product of the location has, is refused with duplicate.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarItemCreate

Responses

StatusDescriptionBody
201CreatedColourBarItem
defaultAny failure. See the Errors section.Error

Get a colour bar item

GET /v1/locations/{locationId}/colour-bar-items/{colourBarItemId}

Scope: products:read

Stability: preview

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarItemIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarItem
defaultAny failure. See the Errors section.Error

Get a colour bar item by id

GET /v1/colour-bar-items/{colourBarItemId}

Scope: products:read

Stability: preview

The same colour bar item as under its location, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries locationId.

Parameters

NameInTypeRequiredDescription
colourBarItemIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarItem
defaultAny failure. See the Errors section.Error

Update a colour bar item

PATCH /v1/locations/{locationId}/colour-bar-items/{colourBarItemId}

Scope: stock:write

Stability: preview

Changes only the fields in the request. Either all of them are changed or none. See ColourBarItemUpdate for how to clear a field. An item stays in its range, and its stock is not changed here.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarItemIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarItemUpdate

Responses

StatusDescriptionBody
200OKColourBarItem
defaultAny failure. See the Errors section.Error

Delete a colour bar item

DELETE /v1/locations/{locationId}/colour-bar-items/{colourBarItemId}

Scope: stock:write

Stability: preview

Removes the item from the colour bar with whatever stock it holds, and frees its own barcodes.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarItemIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Responses

StatusDescriptionBody
204No Content
defaultAny failure. See the Errors section.Error

Add a barcode to a colour bar item

POST /v1/locations/{locationId}/colour-bar-items/{colourBarItemId}/eans

Scope: stock:write

Stability: preview

Gives the item a barcode of its own, as when a delivery row was matched by its article number and its barcode is new. A barcode that another item or a product of the location has is refused with duplicate.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarItemIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarBarcode

Responses

StatusDescriptionBody
200OKColourBarItem
defaultAny failure. See the Errors section.Error

Remove a barcode from a colour bar item

DELETE /v1/locations/{locationId}/colour-bar-items/{colourBarItemId}/eans/{ean}

Scope: stock:write

Stability: preview

Removes one of the item's own barcodes. Removing one of its catalogueEans is refused with not_allowed.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarItemIdpathstringYes
eanpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Responses

StatusDescriptionBody
200OKColourBarItem
defaultAny failure. See the Errors section.Error

Colour bar mixes

Industry: hair and beauty. The Colour bar mixes API lets an integration register what staff mix, read it, undo it and total it per staff member. It is for an integration that weighs or doses colour itself and wants Cliento's stock and totals to follow.

A mix is what a staff member mixed for one customer. It has an id of the form cbm_... and belongs to a location. A mix has one or more bowls. A bowl has components. A component names one colour bar item and how many grams were taken from it.

Registering a mix takes the grams used from each item's stock. The grams are added to the item's openUsed. When a pack is finished, the item's packs goes down by one. That change is recorded as a stock movement of the type withdrawal.

Mixes are under /v1/locations/{locationId}/colour-bar-mixes. A mix is also read by its id, without its location, at /v1/colour-bar-mixes/{colourBarMixId}. Reading needs the scope products:read. Registering needs stock:write. Undoing needs stock:correct.

  • Amounts are whole grams, as weighed. For an item with no pack size the amount is whole packs.
  • A pack leaves the stock when it is finished. The caller says so with openedNewPack: true on the component for which a new pack was opened. If the finished pack ran out midway, fromFinishedPack says how many grams of the amount still came out of it. What was never taken from the finished pack is kept on the component as residue.
  • A pack also counts as finished without the caller saying so, when more has been taken from it than it holds, unless the location has switched that off in Cliento. That setting is not readable through the API: read packsFinished on each component of the answer to see what the mix took from stock.
  • A mix is never refused because an item is out of stock. What was mixed has been mixed; the item's packs stays at 0.
  • listValue is what the mix took at the supplier's list price, VAT excluded, worked out when the mix is registered and kept. A later change of a list price does not change it. A component's listValue has up to four decimals; the mix's is their sum rounded to two.
  • Give the mix your own externalReference. Sending the same reference again changes nothing and answers 200 with the mix made the first time, also when that mix has been undone. A reference already used for a mix by another staff member is refused with not_allowed. To find the mix for a reference, list with externalReference.
  • staffId names the staff member who mixed. Read it from the Staff API.
  • personId also saves the mix on that person as a recipe, in the same call, and the mix then carries its recipeId. It needs the scope customers:write as well.
  • A mix is not changed. A mistake is undone: every pack the mix took is put back, the grams it added to each item's openUsed are taken off again, and its recipe is removed. The mix is then registered again under a new externalReference. An undone mix stays readable, with undoneAt.
  • The summary totals the mixes of a period per staff member at listValue, leaving out the ones that were undone. A location uses these totals to charge the colour used to a staff member who rents a chair.
  • A location that keeps medical records, such as a clinic, has no colour bar mixes: every call is refused with not_allowed.

List colour bar mixes

GET /v1/locations/{locationId}/colour-bar-mixes

Scope: products:read

Stability: preview

The location's mixes, newest first, one page at a time, including those that were undone. With staffId, one staff member's. With externalReference, the mix registered under that reference, if there is one; it is sent without staffId and after.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
limitqueryinteger (int32)NoPage size, 1 to 200. Default 50.
afterquerystringNoThe nextCursor of the previous page.
staffIdquerystringNoOnly the mixes of this staff member.
externalReferencequerystringNoOnly the mix with this external reference. Not together with staffId or after.

Responses

StatusDescriptionBody
200OKColourBarMixList
defaultAny failure. See the Errors section.Error

Register a colour bar mix

POST /v1/locations/{locationId}/colour-bar-mixes

Scope: stock:write

Stability: preview

Registers what was mixed and changes the colour bar items it names. It is never refused because an item is out of stock: what was mixed has been mixed. Send an externalReference, your own id for the mix, to make the call safe to repeat: when the location already has a mix under it, that mix is returned unchanged with 200, and a reference used for another staff member's mix is refused with not_allowed. With personId the mix is also saved on that person as a recipe, which needs the scope customers:write as well. Not available at a location that keeps medical records.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarMixCreate

Responses

StatusDescriptionBody
200A mix with this externalReference already existed.ColourBarMix
201The mix was registered.ColourBarMix
defaultAny failure. See the Errors section.Error

Get a colour bar mix

GET /v1/locations/{locationId}/colour-bar-mixes/{colourBarMixId}

Scope: products:read

Stability: preview

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarMixIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarMix
defaultAny failure. See the Errors section.Error

Get a colour bar mix by id

GET /v1/colour-bar-mixes/{colourBarMixId}

Scope: products:read

Stability: preview

The same colour bar mix as under its location, found from its id. For a caller that holds an id and not the location it belongs to, such as one read from a stock movement. The answer carries locationId.

Parameters

NameInTypeRequiredDescription
colourBarMixIdpathstringYes

Responses

StatusDescriptionBody
200OKColourBarMix
defaultAny failure. See the Errors section.Error

Total colour bar mixes per staff member

GET /v1/locations/{locationId}/colour-bar-mixes/summary

Scope: products:read

Stability: preview

What was mixed from from to to, both days included, in the location's time zone, per staff member, at list price. Mixes that were undone are left out. The period is at most 366 days. A location uses these totals to charge the colour used to a staff member who rents a chair.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
fromquerystring (date)YesThe first day, as YYYY-MM-DD.
toquerystring (date)YesThe last day, as YYYY-MM-DD.
staffIdquerystringNoOnly this staff member.

Responses

StatusDescriptionBody
200OKColourBarMixSummary
defaultAny failure. See the Errors section.Error

Undo a colour bar mix

POST /v1/locations/{locationId}/colour-bar-mixes/{colourBarMixId}/undo

Scope: stock:correct

Stability: preview

Undoes the whole mix, once: every pack it took is put back, the grams it added to each item's openUsed are taken off again, and the recipe it was saved as is removed. The mix stays, with undoneAt. A mix that is already undone is refused with not_allowed.

Parameters

NameInTypeRequiredDescription
locationIdpathstringYes
colourBarMixIdpathstringYes
Idempotency-KeyheaderstringNoA value you make up for this one request, such as a UUID. Send the same value when you retry and the first answer is returned; see Retrying safely. Example: 8e03978e-40d5-43e8-bc93-6894a57f9324.

Request body: ColourBarMixUndo

Responses

StatusDescriptionBody
200OKColourBarMix
defaultAny failure. See the Errors section.Error

Schemas

ColourBarBarcode

FieldTypeRequiredDescription
eanstringYesThe barcode, at most 50 characters. Example: 4064666230412.

ColourBarItem

Represents one thing a location mixes from at its colour bar: one shade of a colour, one strength of a developer, one tub of bleach. Belongs to a colour bar range and to the range's location. Holds its own balance in the location's stock, counted in packs, and how much has been taken from the pack that is open. It is not a product: it is never sold at a point of sale.

FieldTypeRequiredDescription
articleNumberstringNoThe supplier's article number, as read from a delivery note. Example: 99350118254.
catalogueEansarray of stringYesRead-only. Those of eans that the item has from the article in a supplier's catalogue it was made from. They are not the item's own and cannot be removed from it. Can be empty. Example: [].
createdAtstring (date-time)YesExample: 2026-10-12T08:15:30Z.
eansarray of stringYesThe item's barcodes: its own, and those in catalogueEans. Can be empty. Example: ["4064666230412"].
gramsLeftinteger (int64)NoRead-only. Grams left in all the item's packs together. Left out when the item has no pack size. Example: 203.
idstringYesColour bar item id. Example: cbi_3Vn8Kq5TzL1xWc7PdM2RbJ.
listPricestringNoThe list price of one pack, VAT excluded, where the item differs from its range. Left out when the item follows the range's listPrice. Example: 137.00.
listPriceInUsestringNoRead-only. The list price that applies: the item's own, otherwise its range's. Example: 137.00.
locationIdstringYesExample: loc_4fK9xQ2mLr8TzB1vNc7HdW.
namestringYesWhat the item is called. An item without a name of its own is called by its shade, and follows it when the shade is changed. Example: 7/10.
openLeftinteger (int32)NoRead-only. Grams left in the open pack. Left out when no pack is open or the item has no pack size. Example: 23.
openUsedinteger (int32)YesRead-only. Grams taken from the open pack. 0 when no pack is open. Example: 37.
packSizeinteger (int32)NoGrams in one pack, where the item differs from its range. Left out when the item follows the range's packSize. Example: 60.
packSizeInUseinteger (int32)NoRead-only. The pack size that applies: the item's own, otherwise its range's. Left out for an item used a whole pack at a time. Example: 60.
packsinteger (int32)YesRead-only. The packs in stock, the open one included. Never negative. Example: 4.
rangeIdstringYesThe range the item belongs to. Set when the item is created. Example: cbr_7Hc2Lm9QxT4vBn6KdR1WsP.
shadestringNoThe shade of a colour, as the supplier writes it. Example: 7/10.
strengthPercentstringNoThe strength of a developer in per cent, as a decimal string. Example: 6.
unopenedPacksinteger (int32)YesRead-only. The packs that are not opened. Example: 3.
updatedAtstring (date-time)YesWhen the item last changed, which includes its stock and its own barcodes. Example: 2026-10-12T08:15:30Z.

ColourBarItemCreate

FieldTypeRequiredDescription
articleNumberstringNoExample: 99350118254.
eansarray of stringNoThe item's own barcodes. A barcode that another item or a product of the location has is refused. Example: ["4064666230412"].
listPricestringNoThe list price of one pack, VAT excluded, when the item differs from its range. Example: 149.00.
namestringNoWhat the item is called. Required when there is no shade. Example: Blondor Multi Blonde.
packSizeinteger (int32)NoGrams in one pack, when the item differs from its range. Example: 60.
rangeIdstringYesThe range the item belongs to. Example: cbr_7Hc2Lm9QxT4vBn6KdR1WsP.
shadestringNoThe shade of a colour, at most 50 characters. A range holds a shade once. Example: 7/10.
strengthPercentstringNoThe strength of a developer in per cent, greater than 0, at most 100. Example: 6.

ColourBarItemList

FieldTypeRequiredDescription
dataarray of ColourBarItemYes
nextCursorstringNoPass as after to fetch the next page. Absent on the last page. Example: cbi_3Vn8Kq5TzL1xWc7PdM2RbJ.

ColourBarItemUpdate

A JSON merge patch: send only what changes. A field you leave out keeps its value; a field set to null is cleared, but an item must keep a name or a shade. A name equal to the shade is not a name of its own: the item is called by its shade and follows it. Clearing packSize or listPrice makes the item follow its range again.

FieldTypeRequiredDescription
articleNumberstringNoExample: 99350118254.
listPricestringNoExample: 149.00.
namestringNoExample: Blondor Multi Blonde.
packSizeinteger (int32)NoExample: 60.
shadestringNoExample: 7/10.
strengthPercentstringNoExample: 6.

ColourBarMix

Represents what one staff member mixed at a location's colour bar at one time: one or more bowls, each with the colour bar items it took from and how much of each. Belongs to a location. Registering it changes the items it names: what was taken is added to an item's openUsed, and a pack is taken from stock when one is finished. A mix is not changed afterwards; it can be undone.

FieldTypeRequiredDescription
bowlsarray of ColourBarMixBowlYes
createdAtstring (date-time)YesExample: 2026-10-12T08:15:30Z.
externalReferencestringNoYour own id for the mix. Example: mix-2026-10-12-0042.
idstringYesColour bar mix id. Example: cbm_8Wq3Nd6HtY1mKx4LcP9RvB.
listValuestringYesWhat the mix took, at the list prices then, VAT excluded: its components' listValue together, rounded to two decimals, as a decimal string in the location's currency. Example: 91.33.
locationIdstringYesExample: loc_4fK9xQ2mLr8TzB1vNc7HdW.
notestringNoExample: 35 min.
recipeIdstringNoThe recipe the mix was saved as on a person, when it was. Example: rcp_6Jn2Xw8QdT5bVh3ZmK7LsF.
registeredBystringNoThe name of who mixed: the staff member, or the API key when none was named. Example: Anna.
staffIdstringNoThe staff member who mixed. Left out when none was named. Example: stf_2Hs7Bq4MnX9cLk1VtR6PzD.
titlestringNoExample: Roots and lengths.
undoneAtstring (date-time)NoWhen the mix was undone. Left out for a mix that stands. Example: 2026-10-12T09:02:11Z.
undoneBystringNoThe name of who undid the mix. Example: Anna.
updatedAtstring (date-time)YesWhen the mix last changed: when it was undone, otherwise createdAt. Example: 2026-10-12T08:15:30Z.

ColourBarMixBowl

One bowl of a mix.

FieldTypeRequiredDescription
componentsarray of ColourBarMixComponentYes
ratiostringNoColour to developer, as it was sent. Kept as it is. Example: 1:1.
titlestringNoExample: Roots.

ColourBarMixBowlCreate

FieldTypeRequiredDescription
componentsarray of ColourBarMixComponentCreateYes
ratiostringNoColour to developer, such as 1:1 or 1:1.5. Stored as it is. Example: 1:1.
titlestringNoExample: Roots.

ColourBarMixComponent

What a mix took from one colour bar item, and how that left the item.

FieldTypeRequiredDescription
amountinteger (int32)YesHow much was taken: grams, or whole packs of an item that has no pack size. Example: 30.
colourBarItemIdstringYesExample: cbi_3Vn8Kq5TzL1xWc7PdM2RbJ.
fromFinishedPackinteger (int32)NoThe grams of amount that came out of the finished pack before it ran out, when a new pack was opened midway. Example: 12.
listValuestringNoWhat amount was worth at the list price then, VAT excluded, as a decimal string with up to four decimals. Left out when the item had no list price. Example: 68.5000.
namestringYesWhat the item was called when the mix was registered. Example: 7/10.
openUsedinteger (int32)YesThe item's openUsed after this component. Example: 30.
openedNewPackbooleanYesWhether a new pack was opened for this component. Example: false.
packsinteger (int32)YesThe item's packs after this component. Example: 4.
packsFinishedinteger (int32)YesThe packs this component finished, which is what it took from stock. Example: 0.
residueinteger (int32)NoSet only when openedNewPack is true: the pack size less the grams that had been taken from the finished pack. Example: 3.
shadestringNoThe item's shade when the mix was registered. Example: 7/10.

ColourBarMixComponentCreate

FieldTypeRequiredDescription
amountinteger (int32)YesHow much was taken, as a whole number greater than 0: grams as weighed, or whole packs of an item that has no pack size. Example: 30.
colourBarItemIdstringYesExample: cbi_3Vn8Kq5TzL1xWc7PdM2RbJ.
fromFinishedPackinteger (int32)NoWith openedNewPack: the grams of amount that still came out of the finished pack before it ran out. Leave out when the whole amount came from the new pack. Refused with validation_failed for an item that has no pack size. Example: 12.
openedNewPackbooleanNotrue when a new pack was opened for this component: the pack that was open before is then finished and leaves the stock. Example: false.

ColourBarMixCreate

FieldTypeRequiredDescription
bowlsarray of ColourBarMixBowlCreateYes
externalReferencestringNoYour own id for the mix, at most 100 characters. A mix the location already has under it is returned unchanged. Example: mix-2026-10-12-0042.
notestringNoExample: 35 min.
personIdstringNoA person to save the mix on as a recipe, in the same call. Needs the scope customers:write as well. Example: per_9Tk4Yc1WvN7pQe2XhB5MdG.
staffIdstringNoThe staff member who mixed. Read it from the Staff API. Example: stf_2Hs7Bq4MnX9cLk1VtR6PzD.
titlestringNoExample: Roots and lengths.

ColourBarMixList

FieldTypeRequiredDescription
dataarray of ColourBarMixYes
nextCursorstringNoPass as after to fetch the next page. Absent on the last page. Example: cbm_8Wq3Nd6HtY1mKx4LcP9RvB.

ColourBarMixStaffTotal

What one staff member mixed over the period, mixes that were undone left out.

FieldTypeRequiredDescription
listValuestringYesTheir listValue together, as a decimal string. Example: 3480.25.
mixesinteger (int32)YesHow many mixes. Example: 42.
namestringNoExample: Anna.
staffIdstringNoThe staff member. Left out for mixes registered with no staff member. Example: stf_2Hs7Bq4MnX9cLk1VtR6PzD.

ColourBarMixSummary

What was mixed at a location from one day to another, per staff member, at list price.

FieldTypeRequiredDescription
fromstring (date)YesExample: 2026-10-01.
listValuestringYesThe listValue of all staff together, as a decimal string. Example: 12940.75.
staffarray of ColourBarMixStaffTotalYesOne total per staff member who mixed.
tostring (date)YesExample: 2026-10-31.

ColourBarMixUndo

FieldTypeRequiredDescription
staffIdstringNoThe staff member who undoes the mix. Read it from the Staff API. Example: stf_2Hs7Bq4MnX9cLk1VtR6PzD.

ColourBarRange

Represents a supplier's series as a location keeps it at its colour bar, such as one brand's permanent colours. Belongs to a location. Holds what its items have in common: their kind, the size of a pack and its list price. Colour bar items belong to it.

FieldTypeRequiredDescription
brandstringNoExample: Wella.
createdAtstring (date-time)YesExample: 2026-10-12T08:15:30Z.
idstringYesColour bar range id. Example: cbr_7Hc2Lm9QxT4vBn6KdR1WsP.
kindstringYesWhat the range's items are used as, such as colour or developer. A lower-case word; the list is open. Example: colour.
listPricestringNoThe supplier's list price of one pack, VAT excluded, as a decimal string in the location's currency. Example: 137.00.
locationIdstringYesExample: loc_4fK9xQ2mLr8TzB1vNc7HdW.
namestringYesWhat the range is called at the location. Example: Koleston Perfect ME+.
packSizeinteger (int32)NoGrams in one pack of the range's items. Left out for a range whose items are used a whole pack at a time. Example: 60.
seriesstringNoThe supplier's name of the series. Example: KP ME+.
updatedAtstring (date-time)YesWhen the range itself was last changed. Example: 2026-10-12T08:15:30Z.

ColourBarRangeCreate

FieldTypeRequiredDescription
brandstringNoExample: Wella.
kindstringYesWhat the range's items are used as, such as colour or developer: a lower-case word of at most 30 characters. Example: colour.
listPricestringNoThe supplier's list price of one pack, VAT excluded. Example: 137.00.
namestringYesWhat the range is called at the location, at most 255 characters. Example: Koleston Perfect ME+.
packSizeinteger (int32)NoGrams in one pack. Leave out for a range whose items are used a whole pack at a time. Example: 60.
seriesstringNoThe supplier's name of the series. Example: KP ME+.

ColourBarRangeList

FieldTypeRequiredDescription
dataarray of ColourBarRangeYes
nextCursorstringNoPass as after to fetch the next page. Absent on the last page. Example: cbr_7Hc2Lm9QxT4vBn6KdR1WsP.

ColourBarRangeUpdate

A JSON merge patch: send only what changes. A field you leave out keeps its value; a field set to null is cleared. name and kind cannot be cleared.

FieldTypeRequiredDescription
brandstringNoExample: Wella.
kindstringNoExample: colour.
listPricestringNoExample: 137.00.
namestringNoExample: Koleston Perfect ME+.
packSizeinteger (int32)NoGrams in one pack. Changing it changes the pack size of every item of the range that has none of its own. Example: 60.
seriesstringNoExample: KP ME+.

Error

The body of every non-2xx response.

FieldTypeRequiredDescription
codestringYesStable, machine-readable error code. Values today: invalid_request, validation_failed, entity_not_found, duplicate, merchant_required, code_already_used, gift_card_already_used, pin_not_recognised, insufficient_stock, not_allowed, request_in_progress, idempotency_key_reused, unauthenticated, forbidden, account_blocked, rate_limited, route_not_found, method_not_allowed, internal_error.
detailsobject of any valueNoExtra detail. For validation_failed, fieldErrors maps each rejected field to the reason.
messagestringYesHuman-readable explanation. Not stable; do not parse it.