Skip to content

Conventions

View as Markdown

These rules hold for every endpoint in the API.

Request and response bodies are JSON, so send Content-Type: application/json. The one exception is document uploads, where the request body is the file itself. See Documents.

Every request sends a token in the Authorization header. POST /v1/login, GET /v1/catalog/files, and GET /v1/catalog/search send the app token. Every other endpoint sends the user token. See Authentication.

Every Beauty Router ID is a prefix, a hyphen, and a base62 string, for example prod-4Fz9QbX2kL. Treat IDs as opaque strings. Do not parse them or assume their length.

Prefix Object
loc Salon location, which is a company in Beauty Router
user User
lic License
exc Exemption certificate
order Order
prod Product
group Product group
brand Brand
sup Supplier, which is a brand or distributor
cat Category
match Product match
svc Service
event Webhook event
card Payment card

You send your own IDs as externalSalonLocationId and externalUserId when you log in a user, and as externalId when you send products for matching. Each one is any string up to 128 characters.

Timestamps are ISO 8601 in UTC, for example 2026-10-28T19:03:55Z. Dates without a time, such as a license expiration date, are ISO 8601 dates, for example 2027-06-30.

Always send timestamps in UTC, ending in Z. A timestamp with a time zone, such as 2026-10-28T12:03:55-07:00, fails with validation_failed, because it can lead to errors.

Amounts are decimal numbers in dollars, with a currency field next to them. The currency is always "usd".

{
"total": 275.01,
"currency": "usd"
}

Each currency has a fixed precision. For usd it is two decimal places. An amount with more decimal places than the currency supports fails with validation_failed.

The API does not use PATCH. An endpoint accepts a partial update only when its documentation says so, as PUT /v1/company does. Send PUT with only the fields you change, and fields you leave out stay as they are.

Terminal window
curl -X PUT https://api.beautyrouter.com/v1/company \
-H "Authorization: Bearer $USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "displayName": "Golden Hour Hair Studio" }'

Every other PUT endpoint takes the full value.

Only some endpoints support paging. Each endpoint’s documentation says whether it does. Those endpoints use cursor paging with two query parameters:

Parameter Description
limit How many items to return. The default is 50, and the maximum is 200.
startingAfter The ID of the last item on the previous page. Leave it out for page 1.

A paged list returns data with the items and hasMore, which is true when another page follows.

Terminal window
curl "https://api.beautyrouter.com/v1/product-matches?limit=100" \
-H "Authorization: Bearer $USER_TOKEN"
{
"data": [
{
"id": "match-3Pa8sDf2Gh",
"externalId": "inv-10482",
"status": "matched",
"productId": "prod-4Fz9QbX2kL",
"createdAt": "2026-10-27T09:14:02Z",
"updatedAt": "2026-10-27T09:14:02Z"
},
{
"id": "match-9Lk4jHg7Fd",
"externalId": "inv-10517",
"status": "needs_reply",
"question": "Is this product from Jadewell or Amberlin?",
"createdAt": "2026-10-27T09:14:02Z",
"updatedAt": "2026-10-27T16:40:31Z"
}
],
"hasMore": true
}

To get the next page, send the ID of the last item as startingAfter:

Terminal window
curl "https://api.beautyrouter.com/v1/product-matches?limit=100&startingAfter=match-9Lk4jHg7Fd" \
-H "Authorization: Bearer $USER_TOKEN"

An error has an HTTP status and a body with an error object:

{
"error": {
"code": "validation_failed",
"message": "ein must have 9 digits.",
"field": "ein"
}
}
Field Description
code A stable code. Use it in your code.
message A sentence for developers. It can change, so do not match on it.
field The request field that caused the error. Only some errors have it.
missing Only on verification_data_missing and app_setup_incomplete: what still needs to be set.
quote Only on order_total_changed and order_has_problems: a fresh quote.

Errors lists every code, with what it means and how to fix it.

For a 401 with user_token_expired or invalid_user_token, log the user in again with POST /v1/login and repeat the request. See Authentication.