Skip to content

Log in a user

View as Markdown
POST
/login
  • Production and sandbox. The token decides the environment.https://api.beautyrouter.com/v1/login
curl --request POST \
--url https://api.beautyrouter.com/v1/login \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "externalSalonLocationId": "location-2048", "externalUserId": "staff-7731", "firstName": "Clara", "lastName": "Whitfield", "email": "clara.whitfield@example.com" }'

Registers a new company and user, or logs in existing ones, and returns a user token that lasts 24 hours. When the user’s name or email changed, it updates them. Send the salon location’s ID as externalSalonLocationId: each location is its own company. Each login returns a new token, and the user’s earlier tokens keep working.

Beauty Router checks that a new or changed email can receive mail. If it cannot, the login fails with an error that names the problem. If the address may cause trouble, the login succeeds and warnings names the problem.

canOrder says whether the user can create orders or only view the marketplace. Each login sets it, so the latest value wins. With canOrder: false, the user cannot place, change, or cancel an order, change the payment card, or archive a supplier. canManageCompany works the same way: with false, the user cannot change the company’s details, licenses, or exemption certificates, or submit it for review. Your salon app decides who gets which value.

Media typeapplication/json
object
externalSalonLocationId
required

Your ID for the salon location. Each location is its own company.

string
>= 1 characters <= 128 characters
externalUserId
required

Your ID for the user. A user is the combination of the salon location and this ID.

string
>= 1 characters <= 128 characters
firstName
required

The user’s first name.

string
>= 1 characters <= 80 characters
lastName
required

The user’s last name.

string
>= 1 characters <= 80 characters
email
required

The user’s verified email. Beauty Router checks that a new or changed email can receive mail.

string format: email
canOrder

Whether the user can create orders or only view the marketplace. Each login sets it, so the latest value wins. A login that leaves it out sets it to true.

boolean
default: true
canManageCompany

Whether the user can change company settings. Each login sets it, so the latest value wins. A login that leaves it out sets it to true.

boolean
default: true

Examples

ExampleLog in a user
{
"externalSalonLocationId": "location-2048",
"externalUserId": "staff-7731",
"firstName": "Clara",
"lastName": "Whitfield",
"email": "clara.whitfield@example.com"
}

The user is logged in.

Media typeapplication/json
object
userToken
required

The user token, such as br-usertoken-live-<token>. Send it as Authorization: Bearer <token>.

string
expiresAt
required

When the user token expires, 24 hours after login.

string format: date-time
company
required
object
id
required

The company ID.

string
verificationStatus
required

unverified: not submitted yet. in_review: Beauty Router is reviewing the company. prequalified: the initial check passed, and the detailed verification is still pending. The company can order, its orders wait until that verification ends, and no charge happens until then. verified: the company passed the review. declined: the company did not pass the review.

string
Allowed values: unverified in_review prequalified verified declined
user
required
object
id
required

The user ID.

string
warnings

Problems with the email that did not stop the login. email_mailbox_full: the mailbox is full right now. email_temporary_address: the address belongs to a disposable email service. Present only when there is one.

Array<string>
Allowed values: email_mailbox_full email_temporary_address

Examples

ExampleNew company
{
"userToken": "br-usertoken-live-Zk3pV9qL2xTn8RbW4mYc6HdJ0sFa1GeQ7uKo5NiP",
"expiresAt": "2026-10-30T14:05:00Z",
"company": {
"id": "loc-7Hk2pQx9Lm",
"verificationStatus": "unverified"
},
"user": {
"id": "user-3Vb8nWq1Rt"
}
}

validation_failed: a field is missing or has a wrong value. 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.

Media typeapplication/json

The body of every error response.

object
error
required
object
code
required

A stable error code.

string
Allowed values: invalid_app_token invalid_user_token user_token_expired origin_not_allowed ip_not_allowed user_cannot_manage_company user_cannot_order company_blocked company_not_verified app_setup_incomplete not_found validation_failed email_invalid_format email_domain_not_found email_mailbox_not_found address_state_without_license hazmat_destination ship_to_restricted verification_data_missing document_locked document_already_uploaded file_too_large file_type_not_supported reply_not_expected order_action_not_allowed supplier_refused_cancel order_total_changed order_has_problems idempotency_key_reused idempotency_key_in_use rate_limit_exceeded internal_error
message
required

A sentence for developers. It can change, so do not match on it.

string
field

The request field that caused the error. Only some errors have it.

string
missing

Only on verification_data_missing and app_setup_incomplete. What still needs to be set.

Array<string>
quote

Only on order_total_changed and order_has_problems. A fresh quote.

object
groups
required

One group per supplier. Each group becomes one order.

Array<object>
object
supplierId
required
string
lines
required
Array<object>
object
productId
required
string
quantity
required
integer
unitPrice
required

An amount in dollars, with up to two decimal places.

number
discount
required

The discount on the whole line, in US dollars.

number
total
required

An amount in dollars, with up to two decimal places.

number
productsTotal
required

The total of the lines, in US dollars.

number
orderDiscount
required

The discount on the whole order, in US dollars.

number
shipping
required
object
amount
required

The shipping charge in US dollars, or null when it cannot be worked out.

number | null
kind
required
string
Allowed values: free flat carrier
freeShippingRemaining
required

How much more to order for free shipping, or null when it does not apply.

number | null
salesTax
required

The sales tax in US dollars, or null when it cannot be worked out.

number | null
taxExemption
required
object
certificateId
required

The exemption certificate used, or null.

string | null
notAppliedReason
required

Why no certificate applies, or null when one does.

string | null
Allowed values: no_certificate other_state not_reviewed
total
required

The amount the salon pays for this group in US dollars, or null when it cannot be worked out. Send it back as expectedTotal. A group with problems has no expectedTotal.

number | null
chargeTiming
required

now: Beauty Router charges the card when the order is created. after_verification: the company is prequalified, so the charge waits until its verification ends.

string
Allowed values: now after_verification
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
unresolvedLines
required

The lines no supplier can take.

Array<object>
object
productId
required
string
quantity
required
integer
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
companyProblems
required

What stops every group.

Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
total
required

The sum of all the groups in US dollars, or null when a group’s total is.

number | null
currency
required

Always usd.

string
Allowed value: usd

Examples

{
"error": {
"code": "validation_failed",
"message": "ein must have 9 digits.",
"field": "ein"
}
}

invalid_app_token: the Authorization header has no valid app token, or the token expired or was revoked.

Media typeapplication/json

The body of every error response.

object
error
required
object
code
required

A stable error code.

string
Allowed values: invalid_app_token invalid_user_token user_token_expired origin_not_allowed ip_not_allowed user_cannot_manage_company user_cannot_order company_blocked company_not_verified app_setup_incomplete not_found validation_failed email_invalid_format email_domain_not_found email_mailbox_not_found address_state_without_license hazmat_destination ship_to_restricted verification_data_missing document_locked document_already_uploaded file_too_large file_type_not_supported reply_not_expected order_action_not_allowed supplier_refused_cancel order_total_changed order_has_problems idempotency_key_reused idempotency_key_in_use rate_limit_exceeded internal_error
message
required

A sentence for developers. It can change, so do not match on it.

string
field

The request field that caused the error. Only some errors have it.

string
missing

Only on verification_data_missing and app_setup_incomplete. What still needs to be set.

Array<string>
quote

Only on order_total_changed and order_has_problems. A fresh quote.

object
groups
required

One group per supplier. Each group becomes one order.

Array<object>
object
supplierId
required
string
lines
required
Array<object>
object
productId
required
string
quantity
required
integer
unitPrice
required

An amount in dollars, with up to two decimal places.

number
discount
required

The discount on the whole line, in US dollars.

number
total
required

An amount in dollars, with up to two decimal places.

number
productsTotal
required

The total of the lines, in US dollars.

number
orderDiscount
required

The discount on the whole order, in US dollars.

number
shipping
required
object
amount
required

The shipping charge in US dollars, or null when it cannot be worked out.

number | null
kind
required
string
Allowed values: free flat carrier
freeShippingRemaining
required

How much more to order for free shipping, or null when it does not apply.

number | null
salesTax
required

The sales tax in US dollars, or null when it cannot be worked out.

number | null
taxExemption
required
object
certificateId
required

The exemption certificate used, or null.

string | null
notAppliedReason
required

Why no certificate applies, or null when one does.

string | null
Allowed values: no_certificate other_state not_reviewed
total
required

The amount the salon pays for this group in US dollars, or null when it cannot be worked out. Send it back as expectedTotal. A group with problems has no expectedTotal.

number | null
chargeTiming
required

now: Beauty Router charges the card when the order is created. after_verification: the company is prequalified, so the charge waits until its verification ends.

string
Allowed values: now after_verification
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
unresolvedLines
required

The lines no supplier can take.

Array<object>
object
productId
required
string
quantity
required
integer
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
companyProblems
required

What stops every group.

Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
total
required

The sum of all the groups in US dollars, or null when a group’s total is.

number | null
currency
required

Always usd.

string
Allowed value: usd

Examples

Exampleinvalid_app_token
{
"error": {
"code": "invalid_app_token",
"message": "The app token is missing or not valid."
}
}

app_setup_incomplete: a required setting of your salon app is not set. missing lists what to set in the salon app admin area. company_blocked: Beauty Router blocked this company. ip_not_allowed: the app token was sent from an IP address that is not in your allowed list.

Media typeapplication/json

The body of every error response.

object
error
required
object
code
required

A stable error code.

string
Allowed values: invalid_app_token invalid_user_token user_token_expired origin_not_allowed ip_not_allowed user_cannot_manage_company user_cannot_order company_blocked company_not_verified app_setup_incomplete not_found validation_failed email_invalid_format email_domain_not_found email_mailbox_not_found address_state_without_license hazmat_destination ship_to_restricted verification_data_missing document_locked document_already_uploaded file_too_large file_type_not_supported reply_not_expected order_action_not_allowed supplier_refused_cancel order_total_changed order_has_problems idempotency_key_reused idempotency_key_in_use rate_limit_exceeded internal_error
message
required

A sentence for developers. It can change, so do not match on it.

string
field

The request field that caused the error. Only some errors have it.

string
missing

Only on verification_data_missing and app_setup_incomplete. What still needs to be set.

Array<string>
quote

Only on order_total_changed and order_has_problems. A fresh quote.

object
groups
required

One group per supplier. Each group becomes one order.

Array<object>
object
supplierId
required
string
lines
required
Array<object>
object
productId
required
string
quantity
required
integer
unitPrice
required

An amount in dollars, with up to two decimal places.

number
discount
required

The discount on the whole line, in US dollars.

number
total
required

An amount in dollars, with up to two decimal places.

number
productsTotal
required

The total of the lines, in US dollars.

number
orderDiscount
required

The discount on the whole order, in US dollars.

number
shipping
required
object
amount
required

The shipping charge in US dollars, or null when it cannot be worked out.

number | null
kind
required
string
Allowed values: free flat carrier
freeShippingRemaining
required

How much more to order for free shipping, or null when it does not apply.

number | null
salesTax
required

The sales tax in US dollars, or null when it cannot be worked out.

number | null
taxExemption
required
object
certificateId
required

The exemption certificate used, or null.

string | null
notAppliedReason
required

Why no certificate applies, or null when one does.

string | null
Allowed values: no_certificate other_state not_reviewed
total
required

The amount the salon pays for this group in US dollars, or null when it cannot be worked out. Send it back as expectedTotal. A group with problems has no expectedTotal.

number | null
chargeTiming
required

now: Beauty Router charges the card when the order is created. after_verification: the company is prequalified, so the charge waits until its verification ends.

string
Allowed values: now after_verification
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
unresolvedLines
required

The lines no supplier can take.

Array<object>
object
productId
required
string
quantity
required
integer
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
companyProblems
required

What stops every group.

Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
total
required

The sum of all the groups in US dollars, or null when a group’s total is.

number | null
currency
required

Always usd.

string
Allowed value: usd

Examples

{
"error": {
"code": "app_setup_incomplete",
"message": "Set the required settings in the salon app admin area.",
"missing": [
"webhookUrl",
"orderUrl"
]
}
}

internal_error: something failed on Beauty Router’s side. Try again later.

Media typeapplication/json

The body of every error response.

object
error
required
object
code
required

A stable error code.

string
Allowed values: invalid_app_token invalid_user_token user_token_expired origin_not_allowed ip_not_allowed user_cannot_manage_company user_cannot_order company_blocked company_not_verified app_setup_incomplete not_found validation_failed email_invalid_format email_domain_not_found email_mailbox_not_found address_state_without_license hazmat_destination ship_to_restricted verification_data_missing document_locked document_already_uploaded file_too_large file_type_not_supported reply_not_expected order_action_not_allowed supplier_refused_cancel order_total_changed order_has_problems idempotency_key_reused idempotency_key_in_use rate_limit_exceeded internal_error
message
required

A sentence for developers. It can change, so do not match on it.

string
field

The request field that caused the error. Only some errors have it.

string
missing

Only on verification_data_missing and app_setup_incomplete. What still needs to be set.

Array<string>
quote

Only on order_total_changed and order_has_problems. A fresh quote.

object
groups
required

One group per supplier. Each group becomes one order.

Array<object>
object
supplierId
required
string
lines
required
Array<object>
object
productId
required
string
quantity
required
integer
unitPrice
required

An amount in dollars, with up to two decimal places.

number
discount
required

The discount on the whole line, in US dollars.

number
total
required

An amount in dollars, with up to two decimal places.

number
productsTotal
required

The total of the lines, in US dollars.

number
orderDiscount
required

The discount on the whole order, in US dollars.

number
shipping
required
object
amount
required

The shipping charge in US dollars, or null when it cannot be worked out.

number | null
kind
required
string
Allowed values: free flat carrier
freeShippingRemaining
required

How much more to order for free shipping, or null when it does not apply.

number | null
salesTax
required

The sales tax in US dollars, or null when it cannot be worked out.

number | null
taxExemption
required
object
certificateId
required

The exemption certificate used, or null.

string | null
notAppliedReason
required

Why no certificate applies, or null when one does.

string | null
Allowed values: no_certificate other_state not_reviewed
total
required

The amount the salon pays for this group in US dollars, or null when it cannot be worked out. Send it back as expectedTotal. A group with problems has no expectedTotal.

number | null
chargeTiming
required

now: Beauty Router charges the card when the order is created. after_verification: the company is prequalified, so the charge waits until its verification ends.

string
Allowed values: now after_verification
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
unresolvedLines
required

The lines no supplier can take.

Array<object>
object
productId
required
string
quantity
required
integer
problems
required
Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
companyProblems
required

What stops every group.

Array<object>
object
code
required

What stops a group or the whole request. See Problems.

string
Allowed values: buying_suspended supplier_unavailable address_state_without_license ship_to_restricted hazmat_destination address_not_deliverable connection_required connection_blocked insufficient_stock product_unavailable shipping_unavailable tax_unavailable delivery_address_required delivery_phone_required payment_card_required payment_card_unusable quantity_limit_exceeded order_limit_exceeded order_below_minimum
message
required

A sentence you can show. It can change, so do not match on it.

string
productId

The product. Only on problems with one product.

string
supplierId

The supplier. Only on problems with one supplier.

string
available

How many units can be ordered. Only on insufficient_stock.

integer
total
required

The sum of all the groups in US dollars, or null when a group’s total is.

number | null
currency
required

Always usd.

string
Allowed value: usd

Examples

Exampleinternal_error
{
"error": {
"code": "internal_error",
"message": "Something went wrong. Try again later."
}
}