Cliento API reference: Customers
Base URL: https://api.cliento.com
The Customers APIs let an integration keep a location's customer register in step with another system: find customers, and create, change and delete them.
A customer is one of three types, each with its own API:
- Persons. A person is an individual: the one who books, and the one the location sends reminders to.
- Companies. A company owns a vehicle or pays the invoice.
- Vehicles. A vehicle is what a garage or a car wash works on.
The Customers API searches all three types at once. Use it when you have a phone number or a reference and do not know which type it belongs to.
Each customer belongs to one location. The links between them, such as a vehicle's owner, are not available through the API yet.
What staff record about a person over time, such as a recipe, belongs to that person.
Persons
The Persons API lets an integration list a location's persons, find one, and create, change and delete them.
A person is an individual customer: someone who books an appointment, or the contact person for a company or a vehicle. The location communicates with persons, so the phone number, the email address and the consents for SMS and email reminders are on the person.
A person belongs to one location and has an id of the form per_.... Reading needs the scope
customers:read, and writing needs customers:write.
Finding a person
Filter the list. Each filter matches the whole value, and several together match persons that have all of them:
?email=, an email address. Letter case is ignored.?phoneNumber=, in E.164 format with the plus sign percent-encoded (%2B46701234567). A number that staff typed in another format is not found.?identityNumber=, a personnummer or other identity number as it is stored.?externalReference=, the id you gave the person when you created it.
Only externalReference is unique: no two persons, companies or vehicles at a location share one,
though the reference of a deleted one can be used again. Two persons can share an email address or
a phone number, and sometimes an identity number, so the other filters can return several persons
and you choose between them.
When you do not know whether you are looking for a person, a company or a vehicle, search Customers instead.
Identity numbers
A person can have one identity number issued by an authority. It is sent and returned as
identityNumber, with a type and a number. An identityNumber that is not null needs
both. null in an update removes it. The number is kept as you send it. Only surrounding spaces
and any HTML markup are removed, before it is checked and stored. A personnummer and a
samordningsnummer are digits only, with no hyphen or space.
type | What it is | Accepted number | Example |
|---|---|---|---|
se_personnummer | Swedish personal identity number | Twelve digits, YYYYMMDDNNNC: the full year, the day between 01 and 31, and a valid check digit | 198604122385 |
se_samordningsnummer | Swedish coordination number | Twelve digits like a personnummer, with 60 added to the day (61 to 91), and a valid check digit | 198604722382 |
se_reservnummer | Swedish reserve number, given in healthcare to someone without the two above | 3 to 32 characters: upper-case letters A to Z, digits and hyphens | 19860412AB27 |
foreign | A personal identity number from another country | Any text of 1 to 255 characters | 120486-1234 |
other | Anything else | Any text of 1 to 255 characters | EMP-00417 |
The check digit is the last digit and follows the Luhn algorithm over the last ten digits, that
is, without the century. A number that does not fit its type is refused with validation_failed
and identityNumber.number among the fieldErrors. More types may be added, so accept a type
you do not know in a response.
An identity number is not always unique. A create or an update is normally refused with
duplicate when another person at the location already has the number with the same type.
Staff can still register one number on several persons in Cliento, on purpose. A list filtered on
that number then returns each of them. Do not rely on a type and number identifying exactly
one person.
List persons
GET /v1/locations/{locationId}/persons
Scope: customers:read
Stability: preview
The location's persons, oldest first, one page at a time. To find one, use the filters instead of reading the whole list; "Finding a person" under Persons says how each one matches.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
email | query | string | No | Only persons with exactly this email address, whatever its letter case. Example: anna.lindqvist@example.com. |
phoneNumber | query | string | No | Only persons with exactly this mobile number, in E.164 format. Percent-encode the plus sign as %2B. Example: +46701234567. |
identityNumber | query | string | No | Only persons with exactly this identity number, as it is stored: a Swedish personnummer is twelve digits. Example: 198604122385. |
externalReference | query | string | No | Only the person you created with this externalReference. Example: crm-88121. |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | PersonList |
| default | Any failure. See the Errors section. | Error |
Create a person
POST /v1/locations/{locationId}/persons
Scope: customers:write
Stability: preview
Creates a person at the location. Send an externalReference, your own id for the person, to make the call safe to repeat. When a person at the location already has that reference, that person is returned unchanged with 200 and nothing is created. A person with an identity number that another person at the location already has, with the same type, is normally refused with duplicate.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: PersonCreate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | A person with this externalReference already existed. | Person |
| 201 | The person was created. | Person |
| default | Any failure. See the Errors section. | Error |
Get a person
GET /v1/locations/{locationId}/persons/{personId}
Scope: customers:read
Stability: preview
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Person |
| default | Any failure. See the Errors section. | Error |
Get a person by id
GET /v1/persons/{personId}
Scope: customers:read
Stability: preview
The same person 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
personId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Person |
| default | Any failure. See the Errors section. | Error |
Update a person
PATCH /v1/locations/{locationId}/persons/{personId}
Scope: customers:write
Stability: preview
Changes only the fields in the request. Either all of them are changed or none. See PersonUpdate for how to clear a field.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: PersonUpdate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Person |
| default | Any failure. See the Errors section. | Error |
Delete a person
DELETE /v1/locations/{locationId}/persons/{personId}
Scope: customers:write
Stability: preview
A person with upcoming bookings cannot be deleted. Those bookings are cancelled or deleted in Cliento first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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
| Status | Description | Body |
|---|---|---|
| 204 | No Content | |
| default | Any failure. See the Errors section. | Error |
Recipes
Industry: hair and beauty. The Recipes API is for hair salons. It lets an integration save the colour that was mixed for a customer, so that staff can read it in Cliento at the next visit. It is meant for a system that mixes or measures colour itself, such as a scale or a dispenser.
A recipe belongs to a person and describes one visit. It has one or more bowls. Each bowl lists its components and the amount of each.
Recipes are read and added under /v1/locations/{locationId}/persons/{personId}/recipes. A
recipe has an id of the form rcp_.... Reading needs the scope customers:read, and adding
needs customers:write.
- The list is newest first, so its first recipe is what the person got the last time.
- A recipe also shows in the person's log, the notes staff keep on a person in Cliento, written out as text. Staff can change or remove it there.
- A recipe is not changed through the API. When the mix is adjusted, add a new one.
- A recipe moves no stock. A component can name the product it was taken from (
productId), but the withdrawal is recorded through the Stock movements API. To tie the two together, put theexternalReferenceof that stock withdrawal in the recipe'sstockReference. - Amounts are decimal strings, such as
"22.5", in the unit you send with them. propertiesare your own names and values, for what has no field, such as a processing time. They can be set on the recipe, a bowl or a component. Staff see them in Cliento, written out with the recipe in the person's log.appDatais a JSON object for your own system's use: it is stored and returned as it is, and never shown in Cliento.- A location that keeps medical records, such as a clinic, takes no new recipes: adding one there
is refused with
not_allowed.
List a person's recipes
GET /v1/locations/{locationId}/persons/{personId}/recipes
Scope: customers:read
Stability: preview
The person's recipes, newest first, one page at a time. The first one is what was mixed the last time.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes | |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | RecipeList |
| default | Any failure. See the Errors section. | Error |
Add a recipe to a person
POST /v1/locations/{locationId}/persons/{personId}/recipes
Scope: customers:write
Stability: preview
Adds a recipe to the person. It also shows in the person's log in Cliento, where staff read it. A recipe is not changed afterwards through the API: when the mix is adjusted, add a new recipe. Send an Idempotency-Key so that a repeat of the call does not add the recipe twice. Not available at a location that keeps medical records.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: RecipeCreate
Responses
| Status | Description | Body |
|---|---|---|
| 201 | Created | Recipe |
| default | Any failure. See the Errors section. | Error |
Get a recipe
GET /v1/locations/{locationId}/persons/{personId}/recipes/{recipeId}
Scope: customers:read
Stability: preview
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
personId | path | string | Yes | |
recipeId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Recipe |
| default | Any failure. See the Errors section. | Error |
Companies
The Companies API lets an integration list a location's companies, find one, and create, change and delete them.
A company is a business customer: the owner of a vehicle, or the one that pays the invoice for a job. The location does not communicate with a company about a booking. It communicates with a person, such as the company's contact person.
A company belongs to one location and has an id of the form com_.... Reading needs the scope
customers:read, and writing needs customers:write.
organisationNumberis the Swedish organisation number: ten digits with a valid check digit, with no hyphen. A number that does not fit is refused withvalidation_failed.departmentnames one part of a company, such asUsed cars, for a location that registers each part as a company of its own.- To find a company, filter the list on
organisationNumberor on theexternalReferenceyou gave it. - An organisation number is not always unique. A create or an update is normally refused with
duplicatewhen another company at the location already has the number, whatever itsdepartment. Staff can still register one number on several companies in Cliento, on purpose. That is how the parts of one company come to be several companies. Do not rely on a number identifying exactly one company.
List companies
GET /v1/locations/{locationId}/companies
Scope: customers:read
Stability: preview
The location's companies, oldest first, one page at a time. To find one, filter on its organisation number or your own reference.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
organisationNumber | query | string | No | Only companies with exactly this organisation number, ten digits. Example: 5560360793. |
externalReference | query | string | No | Only the company you created with this externalReference. Example: crm-88121. |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | CompanyList |
| default | Any failure. See the Errors section. | Error |
Create a company
POST /v1/locations/{locationId}/companies
Scope: customers:write
Stability: preview
Creates a company at the location. Send an externalReference, your own id for the company, to make the call safe to repeat. When a company at the location already has that reference, that company is returned unchanged with 200 and nothing is created. A company with an organisation number that another company at the location already has is normally refused with duplicate.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: CompanyCreate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | A company with this externalReference already existed. | Company |
| 201 | The company was created. | Company |
| default | Any failure. See the Errors section. | Error |
Get a company
GET /v1/locations/{locationId}/companies/{companyId}
Scope: customers:read
Stability: preview
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
companyId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Company |
| default | Any failure. See the Errors section. | Error |
Get a company by id
GET /v1/companies/{companyId}
Scope: customers:read
Stability: preview
The same company 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
companyId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Company |
| default | Any failure. See the Errors section. | Error |
Update a company
PATCH /v1/locations/{locationId}/companies/{companyId}
Scope: customers:write
Stability: preview
Changes only the fields in the request. Either all of them are changed or none. See CompanyUpdate for how to clear a field.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
companyId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: CompanyUpdate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Company |
| default | Any failure. See the Errors section. | Error |
Delete a company
DELETE /v1/locations/{locationId}/companies/{companyId}
Scope: customers:write
Stability: preview
A company with upcoming bookings cannot be deleted. Those bookings are cancelled or deleted in Cliento first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
companyId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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
| Status | Description | Body |
|---|---|---|
| 204 | No Content | |
| default | Any failure. See the Errors section. | Error |
Vehicles
Industry: automotive. The Vehicles API is for garages, car washes and other automotive businesses. It lets an integration list a location's vehicles, find one, and create, change and delete them.
A vehicle is what the job is done on: the car, not its owner. The owner is a person or a company. The location communicates with the vehicle's contact person, who is a person.
A vehicle belongs to one location and has an id of the form veh_.... Reading needs the scope
customers:read, and writing needs customers:write.
registrationNumberidentifies the vehicle. A vehicle needs a registration number or adescription; it can have both.make,model,modelYearandcolourare filled in from the Swedish vehicle register when staff look the registration number up in Cliento. They are not set through the API and are left out for a vehicle that has not been looked up.- To find a vehicle, filter the list on
registrationNumberor on theexternalReferenceyou gave it. - A registration number is not always unique. A create or an update is normally refused with
duplicatewhen another vehicle at the location already has the number. Staff can still register one number on several vehicles in Cliento, on purpose. Do not rely on a number identifying exactly one vehicle.
List vehicles
GET /v1/locations/{locationId}/vehicles
Scope: customers:read
Stability: preview
The location's vehicles, oldest first, one page at a time. To find one, filter on its registration number or your own reference.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
registrationNumber | query | string | No | Only vehicles with exactly this registration number. Example: ABC123. |
externalReference | query | string | No | Only the vehicle you created with this externalReference. Example: crm-88121. |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | VehicleList |
| default | Any failure. See the Errors section. | Error |
Create a vehicle
POST /v1/locations/{locationId}/vehicles
Scope: customers:write
Stability: preview
Creates a vehicle at the location. Send an externalReference, your own id for the vehicle, to make the call safe to repeat. When a vehicle at the location already has that reference, that vehicle is returned unchanged with 200 and nothing is created. A vehicle with a registration number that another vehicle at the location already has is normally refused with duplicate.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: VehicleCreate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | A vehicle with this externalReference already existed. | Vehicle |
| 201 | The vehicle was created. | Vehicle |
| default | Any failure. See the Errors section. | Error |
Get a vehicle
GET /v1/locations/{locationId}/vehicles/{vehicleId}
Scope: customers:read
Stability: preview
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
vehicleId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Vehicle |
| default | Any failure. See the Errors section. | Error |
Get a vehicle by id
GET /v1/vehicles/{vehicleId}
Scope: customers:read
Stability: preview
The same vehicle 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
vehicleId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Vehicle |
| default | Any failure. See the Errors section. | Error |
Update a vehicle
PATCH /v1/locations/{locationId}/vehicles/{vehicleId}
Scope: customers:write
Stability: preview
Changes only the fields in the request. Either all of them are changed or none. See VehicleUpdate for how to clear a field.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
vehicleId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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: VehicleUpdate
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Vehicle |
| default | Any failure. See the Errors section. | Error |
Delete a vehicle
DELETE /v1/locations/{locationId}/vehicles/{vehicleId}
Scope: customers:write
Stability: preview
A vehicle with upcoming bookings cannot be deleted. Those bookings are cancelled or deleted in Cliento first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
vehicleId | path | string | Yes | |
Idempotency-Key | header | string | No | A 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
| Status | Description | Body |
|---|---|---|
| 204 | No Content | |
| default | Any failure. See the Errors section. | Error |
Customers
The Customers API searches persons, companies and vehicles at once. Use it when you do not know which type of customer you are looking for. You can search by email address, by phone number, by your own reference, or by an identifying number such as a personnummer or a vehicle registration number.
A search returns a page of matching customers. Each match is a short entry that says which type it is. That type's API has the full record.
The Customers API is read-only. Each type is created, changed and deleted through its own API.
- Each entry is short: its id, its
type, itslocationId, its name (for a vehicle, itsdescription) and the number that identifies it. The id's prefix (per_,com_,veh_) andtypesay where to read the rest: Persons, Companies or Vehicles. - Filters match the whole value, and several together match what has all of them:
?email=,?phoneNumber=(in E.164 format with the plus sign percent-encoded),?number=(an identity number, an organisation number or a registration number) and?externalReference=. Add?type=to keep one type, and repeat it for several. - An
externalReferenceis unique among everything at a location, whatever its type.
List customers of every type
GET /v1/locations/{locationId}/customers
Scope: customers:read
Stability: preview
The location's persons, companies and vehicles in one list of short entries, oldest first. Use it to find something when you do not know its type, for example from a phone number; then read it in full from Persons, Companies or Vehicles, as the id's prefix and type say.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
type | query | array of string | No | Only these kinds: person, company or vehicle. Repeat the parameter for several. Example: person. |
email | query | string | No | Only those with exactly this email address. Letter case is ignored. Example: anna.lindqvist@example.com. |
phoneNumber | query | string | No | Only those with exactly this mobile number, in E.164 format. Percent-encode the plus sign as %2B. Example: +46701234567. |
number | query | string | No | Only those with exactly this number: an identity number, an organisation number or a registration number. Example: ABC123. |
externalReference | query | string | No | Only the one you created with this externalReference. Example: crm-88121. |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | CustomerList |
| default | Any failure. See the Errors section. | Error |
List customers across locations
GET /v1/customers
Scope: customers:read
Stability: preview
Lists the persons, companies and vehicles of every location this API key can be used on, as short entries, one page at a time. The call works only when sharing customers between locations is turned on for the organisation in Cliento. Otherwise it is refused with not_allowed, and you list customers per location instead. Each entry has the locationId it is registered at. Read the full record, change it or delete it under that location, in Persons, Companies or Vehicles. The filters work as on a location's list.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
email | query | string | No | Only those with exactly this email address. Letter case is ignored. Example: anna.lindqvist@example.com. |
phoneNumber | query | string | No | Only those with exactly this mobile number, in E.164 format. Percent-encode the plus sign as %2B. Example: +46701234567. |
externalReference | query | string | No | Only those you created with this externalReference. A reference is unique within a location, not across them, so the list can return one match per location. Example: crm-88121. |
number | query | string | No | Only those with exactly this number: an identity number, an organisation number or a registration number. Example: ABC123. |
type | query | array of string | No | Only these kinds: person, company or vehicle. Repeat the parameter for several. Example: person. |
limit | query | integer (int32) | No | Page size, 1 to 200. Default 50. |
after | query | string | No | The nextCursor of the previous page. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | CustomerList |
| default | Any failure. See the Errors section. | Error |
Get a customer of any type
GET /v1/locations/{locationId}/customers/{customerId}
Scope: customers:read
Stability: preview
The short entry for a person, a company or a vehicle, by its id.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
locationId | path | string | Yes | |
customerId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Customer |
| default | Any failure. See the Errors section. | Error |
Get a customer of any type by id
GET /v1/customers/{customerId}
Scope: customers:read
Stability: preview
The short entry for a person, a company or a vehicle, found from its id. For a caller that holds an id and not the location it belongs to. The answer carries locationId.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
customerId | path | string | Yes |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | OK | Customer |
| default | Any failure. See the Errors section. | Error |
Customer log
Coming soon. Read and add the notes and files staff keep on a person, a company or a vehicle.
Schemas
Address
| Field | Type | Required | Description |
|---|---|---|---|
city | string or null | No | Example: Stockholm. |
country | string or null | No | Free text; an ISO 3166-1 alpha-2 code is recommended. Example: SE. |
line1 | string or null | No | Example: Storgatan 12. |
line2 | string or null | No | Example: Lgh 1102. |
line3 | string or null | No | |
postCode | string or null | No | Example: 111 51. |
Communication
What the person has agreed to receive. In an update, a field you leave out keeps its value. For a new person smsReminders, emailReminders and reviewReminders start as true and marketing as false: send marketing as true only when the person has agreed to marketing.
| Field | Type | Required | Description |
|---|---|---|---|
emailReminders | boolean | No | Booking reminders by email. |
marketing | boolean | No | Marketing messages. |
reviewReminders | boolean | No | Requests to review a visit. |
smsReminders | boolean | No | Booking reminders by SMS. |
Company
Represents a business a location serves. Belongs to one location.
| Field | Type | Required | Description |
|---|---|---|---|
address | Address | No | |
createdAt | string (date-time) | No | |
department | string | No | A part of the company, when the location serves several of them. Example: Used cars. |
email | string | No | Example: info@example.com. |
externalReference | string | No | Your own id for it, as sent when it was created. Example: crm-88121. |
id | string | Yes | Example: com_6Tn3wRd8Kq1Vb5Xs9LmPyA. |
locationId | string | Yes | Example: loc_4fK9xQ2mLr8TzB1vNc7HdW. |
name | string | No | Example: Bilfirman AB. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
organisationNumber | string | No | The Swedish organisation number: ten digits with a valid check digit, with no hyphen. Example: 5560360793. |
otherPhoneNumber | string | No | Example: +4686543210. |
phoneNumber | string | No | Phone number, in E.164 format when it was set through this API. Example: +46701234567. |
updatedAt | string (date-time) | No |
CompanyCreate
| Field | Type | Required | Description |
|---|---|---|---|
address | Address | No | |
department | string | No | A part of the company, when the location serves several of them. Example: Used cars. |
email | string | No | Example: info@example.com. |
externalReference | string | No | Your own id for it, at most 100 characters, such as its id in your system. It makes the create safe to repeat and lets you find it again. Compared exactly, letter case included. Example: crm-88121. |
name | string | Yes | Example: Bilfirman AB. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
organisationNumber | string | No | The Swedish organisation number: ten digits with a valid check digit, with no hyphen. Example: 5560360793. |
otherPhoneNumber | string | No | Example: +4686543210. |
phoneNumber | string | No | Phone number in E.164 format: a plus sign, the country code and the number, at most 15 digits. Example: +46701234567. |
CompanyList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Company | Yes | |
nextCursor | string | No | Pass as after to fetch the next page. Absent on the last page. Example: com_6Tn3wRd8Kq1Vb5Xs9LmPyA. |
CompanyUpdate
A JSON merge patch: send only what changes. A field you leave out keeps its value; a field set to null is cleared, except name, which cannot be cleared. address merges field by field.
| Field | Type | Required | Description |
|---|---|---|---|
address | Address or null | No | |
department | string or null | No | A part of the company, when the location serves several of them. Example: Used cars. |
email | string or null | No | Example: info@example.com. |
name | string | No | Example: Bilfirman AB. |
notes | string or null | No | Staff-facing notes, at most 1000 characters. |
organisationNumber | string or null | No | The Swedish organisation number: ten digits with a valid check digit, with no hyphen. Example: 5560360793. |
otherPhoneNumber | string or null | No | Example: +4686543210. |
phoneNumber | string or null | No | Phone number in E.164 format: a plus sign, the country code and the number, at most 15 digits. Example: +46701234567. |
Customer
The short entry for a person, a company or a vehicle. The id's prefix says which type, and that type's API has the rest.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Example: per_2QCtWVSaVO7yCRYBj1zsbA. |
locationId | string | Yes | Example: loc_4fK9xQ2mLr8TzB1vNc7HdW. |
name | string | No | Example: Anna Lindqvist. |
number | string | No | The number that identifies it, when it has one: a person's identity number, a company's organisation number or a vehicle's registration number. Example: 198604122385. |
type | string | Yes | person, company or vehicle. It also says where to read the rest: Persons, Companies or Vehicles. More values may be added. Example: person. |
CustomerList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Customer | Yes | |
nextCursor | string | No | Pass as after to fetch the next page. Absent on the last page. Example: per_2QCtWVSaVO7yCRYBj1zsbA. |
CustomerOwner
Whose customer a person is within its location: the location's own, or that of one of the location's resources. A salon that rents out chairs uses it: a person served by a hairdresser who rents a chair is that resource's customer, and a person served by an employee is the location's. Many locations never record it, so unassigned is common and says nothing either way.
| Field | Type | Required | Description |
|---|---|---|---|
resourceId | string | No | The resource (see Resources) whose customer the person is. Present when type is resource. Example: res_2QCtWVSaVO7yCRYBj1zsbA. |
type | string | Yes | location: the location's own customer. resource: the customer of one resource, named by resourceId. unassigned: not recorded. More values may be added. Values today: location, resource, unassigned. |
Error
The body of every non-2xx response.
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Stable, 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. |
details | object of any value | No | Extra detail. For validation_failed, fieldErrors maps each rejected field to the reason. |
message | string | Yes | Human-readable explanation. Not stable; do not parse it. |
IdentityNumber
A number issued by an authority that identifies a person, such as a personnummer. The accepted format of each type is listed under Persons.
| Field | Type | Required | Description |
|---|---|---|---|
number | string | Yes | In the format of its type: twelve digits for a Swedish personnummer. Example: 198604122385. |
type | string | Yes | The kind of number, in lower case, such as se_personnummer or foreign. More values may be added. Example: se_personnummer. |
Person
Represents an individual a location serves. Belongs to one location.
| Field | Type | Required | Description |
|---|---|---|---|
address | Address | No | |
communication | Communication | Yes | |
createdAt | string (date-time) | No | |
dateOfBirth | string | No | ISO 8601 date. Example: 1986-04-12. |
email | string | No | Example: anna.lindqvist@example.com. |
externalReference | string | No | Your own id for it, as sent when it was created. Example: crm-88121. |
gender | string | No | One lower-case word such as female. More values may be added. Example: female. |
id | string | Yes | Example: per_2QCtWVSaVO7yCRYBj1zsbA. |
identityNumber | IdentityNumber | No | |
locationId | string | Yes | Example: loc_4fK9xQ2mLr8TzB1vNc7HdW. |
name | string | No | Example: Anna Lindqvist. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
onlineBookingBlocked | boolean | Yes | True when the person may not book online. |
otherPhoneNumber | string | No | Example: +4686543210. |
owner | CustomerOwner | Yes | Whose customer the person is within the location. See CustomerOwner. |
phoneNumber | string | No | Mobile number, in E.164 format when it was set through this API. Example: +46701234567. |
updatedAt | string (date-time) | No |
PersonCreate
| Field | Type | Required | Description |
|---|---|---|---|
address | Address | No | |
communication | Communication | No | |
dateOfBirth | string | No | ISO 8601 date. Example: 1986-04-12. |
email | string | No | Example: anna.lindqvist@example.com. |
externalReference | string | No | Your own id for it, at most 100 characters, such as its id in your system. It makes the create safe to repeat and lets you find it again. Compared exactly, letter case included. Example: crm-88121. |
gender | string | No | Values today: male, female, other. |
identityNumber | IdentityNumber | No | |
name | string | Yes | Example: Anna Lindqvist. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
onlineBookingBlocked | boolean | No | Set to true to stop the person booking online. |
otherPhoneNumber | string | No | Example: +4686543210. |
phoneNumber | string | No | Mobile number in E.164 format: a plus sign, the country code and the number, at most 15 digits. Example: +46701234567. |
PersonList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Person | Yes | |
nextCursor | string | No | Pass as after to fetch the next page. Absent on the last page. Example: per_2QCtWVSaVO7yCRYBj1zsbA. |
PersonUpdate
A JSON merge patch: send only what changes. A field you leave out keeps its value; a text field, identityNumber or address set to null is cleared, except name, which cannot be cleared. address merges field by field; identityNumber is replaced as a whole. The booleans (communication.*, onlineBookingBlocked) are true or false and cannot be null.
| Field | Type | Required | Description |
|---|---|---|---|
address | Address or null | No | |
communication | Communication | No | |
dateOfBirth | string or null | No | ISO 8601 date. Example: 1986-04-12. |
email | string or null | No | Example: anna.lindqvist@example.com. |
gender | string or null | No | Values today: male, female, other, null. |
identityNumber | IdentityNumber or null | No | |
name | string | No | Example: Anna Lindqvist. |
notes | string or null | No | Staff-facing notes, at most 1000 characters. |
onlineBookingBlocked | boolean | No | Set to true to stop the person booking online. |
otherPhoneNumber | string or null | No | Example: +4686543210. |
phoneNumber | string or null | No | Mobile number in E.164 format: a plus sign, the country code and the number, at most 15 digits. Example: +46701234567. |
Recipe
A record of what was mixed for a person at one visit. Belongs to that person.
| Field | Type | Required | Description |
|---|---|---|---|
appData | object of any value | No | The JSON object of your own that is stored with the recipe, returned as it is. Example: {"formulaId":"F-2291"}. |
bowls | array of RecipeBowl | Yes | The bowls mixed, in order. |
createdAt | string (date-time) | Yes | Example: 2026-10-11T09:24:31Z. |
id | string | Yes | Example: rcp_4Kd8sWn2Qy6Hb9Tf3LmVxA. |
note | string | No | Example: Slightly warmer than last time.. |
personId | string | Yes | Example: per_6Jm2tRx8Lc4Nq7Bv5ZgWkD. |
properties | object of string | No | Example: {"processingTime":"35 min"}. |
stockReference | string | No | Example: treatment-2026-10-11-0042. |
title | string | No | Example: Colour, roots and lengths. |
updatedAt | string (date-time) | No | When staff last changed the recipe in Cliento. Left out when they never have. Example: 2026-10-12T14:02:10Z. |
RecipeBowl
One bowl: what was mixed together, usually colour and a developer.
| Field | Type | Required | Description |
|---|---|---|---|
components | array of RecipeComponent | Yes | What went into the bowl, 1 to 20. |
properties | object of string | No | Your own names and values for this bowl, with the same limits as a component's properties. Example: {"processingTime":"35 min"}. |
ratio | string | No | Parts of colour to parts of developer. Example: 1:2. |
title | string | No | What the bowl is for. At most 200 characters. Example: Roots. |
RecipeComponent
One thing that went into a bowl.
| Field | Type | Required | Description |
|---|---|---|---|
amount | string | Yes | How much, in unit, as a decimal string greater than 0 with at most three decimals. Example: 30. |
name | string | Yes | What it is, as the hairdresser reads it. At most 200 characters. Example: Koleston Perfect 7/0. |
productId | string | No | The product the component was taken from, when it is one of the location's. Example: prd_5Tg8mPq1Xc7Jd2Ls9WbNrK. |
properties | object of string | No | Your own names and values for this component, at most 30. A name is at most 100 characters and a value at most 500. Example: {"brand":"Wella"}. |
role | string | No | What the component is in the mix, as one lower-case word such as colour or developer. The list is open, so accept a value you do not know. Example: colour. |
shade | string | No | The shade code of a colour. At most 50 characters. Example: 7/0. |
strengthPercent | string | No | The strength of a developer in per cent, as a decimal string greater than 0 and at most 100, with at most two decimals. Example: 6. |
unit | string | Yes | The unit of amount, as the hairdresser reads it. At most 20 characters. Example: g. |
RecipeCreate
What was mixed for a person at one visit.
| Field | Type | Required | Description |
|---|---|---|---|
appData | object of any value | No | A JSON object of your own, for what the recipe has no field for. It is stored and returned as it is, and never shown in Cliento. At most 16 kB. A number keeps the precision of a double; send a longer one as a string. Example: {"formulaId":"F-2291"}. |
bowls | array of RecipeBowl | Yes | The bowls mixed, 1 to 20, in order. |
note | string | No | Free text. At most 4000 characters. Example: Slightly warmer than last time.. |
properties | object of string | No | Your own names and values for the whole recipe, with the same limits as a component's properties. Example: {"processingTime":"35 min"}. |
staffId | string | No | The staff member who made the recipe, shown as its author in the person's log. Without it the author is the API key. Example: stf_7Hn3kQw9Zr4Tb6Vy1MxPdE. |
stockReference | string | No | The externalReference of the stock document that took the recipe's products out of stock, when you recorded one. At most 100 characters. Example: treatment-2026-10-11-0042. |
title | string | No | What the recipe is for. At most 200 characters. Example: Colour, roots and lengths. |
RecipeList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Recipe | Yes | |
nextCursor | string | No | Pass as after to fetch the next page. Absent on the last page. Example: rcp_4Kd8sWn2Qy6Hb9Tf3LmVxA. |
Vehicle
Represents a vehicle a location works on. Belongs to one location.
| Field | Type | Required | Description |
|---|---|---|---|
colour | string | No | From the vehicle register. Example: Red. |
createdAt | string (date-time) | No | |
description | string | No | What the vehicle is called in Cliento. A lookup in the vehicle register fills it in with the make, model, colour and year; staff can change it. Example: The red van. |
externalReference | string | No | Your own id for it, as sent when it was created. Example: crm-88121. |
id | string | Yes | Example: veh_3Ks7pQx2Wn9Tb4Vd6HyRcE. |
locationId | string | Yes | Example: loc_4fK9xQ2mLr8TzB1vNc7HdW. |
make | string | No | From the Swedish vehicle register, when staff have looked the vehicle up in Cliento. Not set through the API. Example: Volvo. |
model | string | No | From the vehicle register. Example: V60. |
modelYear | integer (int32) | No | From the vehicle register. Example: 2021. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
registrationNumber | string | No | The registration number, one to seven characters. Example: ABC123. |
updatedAt | string (date-time) | No |
VehicleCreate
A vehicle needs a registrationNumber or a description.
| Field | Type | Required | Description |
|---|---|---|---|
description | string | No | What the vehicle is called in Cliento, such as The red van. Example: The red van. |
externalReference | string | No | Your own id for it, at most 100 characters, such as its id in your system. It makes the create safe to repeat and lets you find it again. Compared exactly, letter case included. Example: crm-88121. |
notes | string | No | Staff-facing notes, at most 1000 characters. |
registrationNumber | string | No | The registration number, one to seven characters. Example: ABC123. |
VehicleList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Vehicle | Yes | |
nextCursor | string | No | Pass as after to fetch the next page. Absent on the last page. Example: veh_3Ks7pQx2Wn9Tb4Vd6HyRcE. |
VehicleUpdate
A JSON merge patch: send only what changes. A field you leave out keeps its value; a field set to null is cleared, but a vehicle must keep a registrationNumber or a description.
| Field | Type | Required | Description |
|---|---|---|---|
description | string or null | No | What the vehicle is called in Cliento, such as The red van. Example: The red van. |
notes | string or null | No | Staff-facing notes, at most 1000 characters. |
registrationNumber | string or null | No | The registration number, one to seven characters. Example: ABC123. |