Authentication
Beauty Router uses two tokens. The app token identifies your salon app and stays on your server. The user token identifies one user of your salon app and can go to your frontend.
Both tokens go in the Authorization header:
Authorization: Bearer <token>Each token starts with its type and its environment, so the two types have different formats:
| Token | Production | Sandbox |
|---|---|---|
| App token | br-apptoken-live-<token> |
br-apptoken-sandbox-<token> |
| User token | br-usertoken-live-<token> |
br-usertoken-sandbox-<token> |
A token works only in its own environment. Each endpoint takes one type:
| Endpoint | Token |
|---|---|
POST /v1/login |
App token |
GET /v1/catalog/files |
App token |
GET /v1/catalog/search |
App token |
| Every other endpoint | User token |
GET /v1/catalog/products/{productId} is a catalog endpoint that takes the user token, so your page can call it.
App token
Section titled “App token”You generate app tokens in the salon app admin area, which you can open once Beauty Router has set up your salon app. The admin area shows each token once, so store it on your server right away.
You can have several app tokens at the same time, so you can rotate them safely. Each one can have a lifetime, so it expires on a date you choose.
Keep app tokens on your server. Never put one in browser or mobile code, and never let it leave your security perimeter. Anyone who has one can log in as any user of your salon app and place orders for any company in your client base that has already added a payment card.
An expired or revoked token returns invalid_app_token.
Allowed IP addresses
Section titled “Allowed IP addresses”You can limit where your app tokens work. In the salon app admin area, add IP addresses or ranges, such as 203.0.113.10
or 203.0.113.0/24. A request with an app token from any other address fails with ip_not_allowed. The token stays
active, and the attempt appears in your integration errors.
The list is empty by default, which allows every address. Each environment has its own list. Your servers need fixed outgoing addresses for this. On AWS, Google Cloud, or Azure, that usually means a NAT gateway with a static IP.
New networks
Section titled “New networks”Beauty Router notes the networks your app tokens are used from, such as a cloud provider. When a token is used from a new network, you get a notification. The request still works. This needs no setup, and it works when your cloud addresses change.
Rotate a token
Section titled “Rotate a token”Two tokens can work side by side, so you can replace a token with no downtime:
- Generate a new token in the admin area, with a lifetime that fits your rotation, such as one year.
- Put the new token on your server.
- Limit the lifetime of the old token, so that it expires once all your servers use the new one.
User tokens stay valid when the app token that created them expires. Each one ends after its usual 24 hours.
Beauty Router sends a reminder 30 days and 7 days before a token expires, unless a newer token that you already use outlasts it. The reminder goes to your developer email and Slack webhook, or to your team in the salon app admin area if you set neither.
Revoke a token
Section titled “Revoke a token”If a token leaks, revoke it in the admin area. It stops working at once, and so does every user token it created. Your users get new user tokens at their next login.
User token
Section titled “User token”The user token can go to your frontend. It acts for one user only and lasts 24 hours. Your page can use it to call the
API directly, and the JavaScript library runs on it. A browser request must come from an
origin you added in the salon app admin area. Otherwise it fails with origin_not_allowed, which
means the origin is not registered in your salon app admin area. A browser may report this as a CORS error instead.
A user can have several user tokens at the same time, for example when they open your salon app on a phone and on a computer. Each login returns a new token, and the earlier ones keep working.
Log in a user
Section titled “Log in a user”Your server calls POST /v1/login with the app token and the user’s details. It gets back a user token. Take the user and
the salon location from your own session, never from what the browser sends, because the app token can log in any user.
| Field | Description |
|---|---|
externalSalonLocationId |
Your ID for the salon location, up to 128 characters. |
externalUserId |
Your ID for the user, up to 128 characters. |
firstName |
The user’s first name, up to 80 characters. |
lastName |
The user’s last name, up to 80 characters. |
email |
The user’s verified email. |
canOrder |
Whether the user can create orders or only view the marketplace. Optional, default true. |
canManageCompany |
Whether the user can change company settings. Optional, default true. |
curl https://api.beautyrouter.com/v1/login \ -H "Authorization: Bearer $BEAUTY_ROUTER_APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "externalSalonLocationId": "location-2048", "externalUserId": "staff-7731", "firstName": "Clara", "lastName": "Whitfield", "email": "clara.whitfield@example.com" }'The response has the user token, when it expires, and the Beauty Router IDs of the company and the user:
{ "userToken": "br-usertoken-live-Zk3pV9qL2xTn8RbW4mYc6HdJ0sFa1GeQ7uKo5NiP", "expiresAt": "2026-10-30T14:05:00Z", "company": { "id": "loc-7Hk2pQx9Lm", "verificationStatus": "unverified" }, "user": { "id": "user-3Vb8nWq1Rt" }}Use company.verificationStatus to decide what to show the user. See Companies and verification.
New and returning users
Section titled “New and returning users”The same call registers a new company and a new user, and logs in existing ones. There is no separate registration step: whenever a user needs Beauty Router, your server makes this call. When the user’s name or email changed in your salon app, the call updates them in Beauty Router.
There is no password and no email confirmation. Your salon app vouches for its user, so these checks stay on your side:
- Names. You manage them. Beauty Router stores what you send.
- Email verification. Send only an email the user has verified.
- Email uniqueness. If emails must be unique inside a company, check that yourself. Two users of one company can have the same email.
Email deliverability
Section titled “Email deliverability”Beauty Router checks that a new or changed email can receive mail.
When the address cannot receive mail, the login fails with status 400, field set to email, and a code that names the
problem. Your salon app can then ask the user to check the email or to give another one.
| Code | Problem |
|---|---|
email_invalid_format |
The address is not a valid email address. |
email_domain_not_found |
The domain does not exist or cannot receive email. |
email_mailbox_not_found |
The mail server rejected the address. |
When the address may cause trouble, the login succeeds, Beauty Router keeps the address, and the response has a warnings
list:
{ "userToken": "br-usertoken-live-Zk3pV9qL2xTn8RbW4mYc6HdJ0sFa1GeQ7uKo5NiP", "warnings": ["email_mailbox_full"]}| Warning | What it means |
|---|---|
email_mailbox_full |
The mailbox is full right now, so emails bounce until the user frees space. |
email_temporary_address |
The address belongs to a disposable email service. |
If your salon app accepts such an address, it must handle users who do not receive the emails they expect. A warning comes only with the login that checked the email.
An email passes with no warning in every other case, such as a domain that accepts all mail, or an address that could not
be checked. In the sandbox, addresses at example.com skip the check, so you can test with made-up users.
Salon locations
Section titled “Salon locations”Each salon location is its own company in Beauty Router. Send the location’s ID as externalSalonLocationId. A salon with
three locations is three companies, and each one is verified and orders on its own.
Who counts as one user
Section titled “Who counts as one user”A user is the combination of the salon location and externalUserId. The same externalUserId at another location is a
different user, so a person who works at two locations is two users in Beauty Router.
This rarely matters in practice. Beauty Router keeps no settings that follow a person between locations, and the name, email, and rights come with each login.
Users who cannot order
Section titled “Users who cannot order”canOrder says whether the user can create orders or only view the marketplace. With canOrder: false, the user can
view the marketplace, keep favorites, and fill a cart, but cannot place, change, or cancel an order, change the
payment card, or archive a supplier. Those requests fail with user_cannot_order.
Each login sets canOrder, so the latest value wins. A login that leaves it out sets it to true, so send false
every time you log in that user, including when the token expires.
Your salon app decides who gets which value. Beauty Router has no roles.
Users who cannot change company settings
Section titled “Users who cannot change company settings”canManageCompany says whether the user can change the company’s settings. With canManageCompany: false, the user can
read the company, but cannot change its details, licenses, or exemption certificates, or submit it for review. Those
requests fail with user_cannot_manage_company.
It works like canOrder. Each login sets it, so the latest value wins. A login that leaves it out sets it to true,
so send false every time you log in that user. It does not affect ordering or the payment card, and a user who can
order can still choose a delivery address at checkout.
Only users with canManageCompany get the company emails, except the two card emails, so keep it true for at
least one user of each company.
Incomplete setup
Section titled “Incomplete setup”Login fails with app_setup_incomplete until your salon app’s required settings are set in the
salon app admin area of that environment. missing lists what to set:
{ "error": { "code": "app_setup_incomplete", "message": "Set the required settings in the salon app admin area.", "missing": ["webhookUrl", "orderUrl"] }}The values in missing are name, origins, webhookUrl, webhookSecret, orderUrl, productUrl, verificationUrl,
and marketplaceUrl.
Blocked companies
Section titled “Blocked companies”Beauty Router can block a company, for example for fraud. Its user tokens stop working at once, and a login fails with
company_blocked.
Log out a user
Section titled “Log out a user”POST /v1/logout ends the user token it is called with. Call it from your frontend or your server when the user logs out
of your salon app. The user’s other tokens keep working, for example on another device.
curl -X POST https://api.beautyrouter.com/v1/logout \ -H "Authorization: Bearer $USER_TOKEN"The response is 204 with no body. A later request with that token fails with invalid_user_token.
Token expiry
Section titled “Token expiry”The user token lasts 24 hours. The expiresAt field says when it ends.
There is no refresh token. Call POST /v1/login again when the token expires, or when a request returns 401 with
user_token_expired or invalid_user_token. In the embedded marketplace, the library asks your code for a new token
through getUserToken. See Embedded marketplace.
Environments
Section titled “Environments”The sandbox and production use the same API base URL, https://api.beautyrouter.com/v1. The token decides the
environment: a token that starts with br-apptoken-sandbox- or br-usertoken-sandbox- works in the sandbox, and a
-live- token works in production.
The sandbox runs on the same deployment as production, so it always has the same version. All systems in the sandbox run in test mode.
Each environment has its own salon app admin area, with its own app tokens, origins, and settings. Build and test against the sandbox. When you go live, set up your salon app in the production admin area, and switch the app token and the webhook secret to production. The library loads from https://js.beautyrouter.com/v1/beauty-router.js in both environments, and it takes the environment from the user token.
