# Errors

This page lists every error code, with what it means and what to do. See [Errors](/conventions/#errors) for the shape of
an error response. Each entry in the salon app admin area links to its section here.

## Tokens and access

### `invalid_app_token`

Status `401`. The `Authorization` header has no valid app token, or the token expired or was revoked.

Check that the request sends `Authorization: Bearer <token>` with an app token, not a user token. If the token expired
or was revoked, generate a new one in the salon app admin area. See
[Rotate a token](/authentication/#rotate-a-token).

### `invalid_user_token`

Status `401`. The `Authorization` header has no valid user token, or the token was logged out or revoked.

Log the user in again with `POST /v1/login`, then repeat the request. In the embedded marketplace, the library does this
through `getUserToken`. If the error comes back, check that this endpoint [takes a user token](/authentication/).

### `user_token_expired`

Status `401`. The user token ended after its 24 hours.

Log the user in again with `POST /v1/login`, then repeat the request. See
[Token expiry](/authentication/#token-expiry).

### `origin_not_allowed`

Status `403`. The request came from an origin that is not registered in your salon app admin area. A browser may report
this as a CORS error.

Add the origin in the salon app admin area of this environment. See [Get access](/support/#get-access).

### `ip_not_allowed`

Status `403`. The app token was sent from an IP address that is not in your allowed list. The token stays active.

Add the address or its range in the salon app admin area, or send the request from an allowed server. The entry in the
admin area shows the refused address. See [Allowed IP addresses](/authentication/#allowed-ip-addresses).

### `app_setup_incomplete`

Status `403`. A required setting of your salon app is not set, so a login cannot work yet. `missing` lists what to set.

Set each one in the salon app admin area of this environment. See
[Incomplete setup](/authentication/#incomplete-setup).

## Users and companies

### `user_cannot_order`

Status `403`. The user was logged in with `canOrder: false`, so they cannot place, change, or cancel an order, change the
payment card, or archive a supplier.

Hide the action for this user, or log them in with `canOrder: true` if they should have it. See
[Users who cannot order](/authentication/#users-who-cannot-order).

### `user_cannot_manage_company`

Status `403`. The user was logged in with `canManageCompany: false`, so they cannot change the company's details,
licenses, or exemption certificates, or submit it for review.

Hide the action for this user, or log them in with `canManageCompany: true` if they should have it. See
[Users who cannot change company settings](/authentication/#users-who-cannot-change-company-settings).

### `company_blocked`

Status `403`. Beauty Router blocked this company. Its logins and user tokens no longer work.

Write to [dev@beautyrouter.com](mailto:dev@beautyrouter.com).

### `company_not_verified`

Status `403`. The company is not `prequalified` or `verified`, so it cannot see wholesale prices or order.

Finish the company's verification. See [Companies and verification](/companies/#verification-statuses).

### `verification_data_missing`

Status `400`. The company cannot be submitted for review yet. `missing` lists what it needs.

Send each missing item, then submit again. See [Submit for review](/companies/#submit-for-review).

## Requests

### `validation_failed`

Status `400`. A field is missing or has a wrong value. `field` names it, and `message` says what is wrong.

Fix the field and send the request again. Show the problem to the user when the value came from them. A delivery address
that no carrier can reach also returns this error.

### `not_found`

Status `404`. The object does not exist, or the user has no access to it. A user can reach only the objects of their own
company, so another company's object looks the same as one that does not exist.

Check the ID, and check that the user token belongs to the right company.

### `rate_limit_exceeded`

Status `429`. Too many requests.

Wait a moment and try again, with a longer wait after each failure.

### `internal_error`

Status `500`. Something failed on Beauty Router's side.

Try again later. If it keeps happening, send the request ID from the salon app admin area to
[dev@beautyrouter.com](mailto:dev@beautyrouter.com).

## Emails

### `email_invalid_format`

Status `400`. The address is not a valid email address.

Ask the user to check the email. See [Email deliverability](/authentication/#email-deliverability).

### `email_domain_not_found`

Status `400`. The domain does not exist or cannot receive email.

Ask the user to check the email or to give another one.

### `email_mailbox_not_found`

Status `400`. The mail server rejected the address.

Ask the user to check the email or to give another one.

## Delivery addresses

### `address_state_without_license`

Status `400` on `PUT /v1/orders/{orderId}/delivery-address`. On a quote or on `POST /v1/orders/batch`, the code is in `problems`, and the batch fails with [`order_has_problems`](#order_has_problems). The delivery address is in a state where the company has no license.

Add a [license](/companies/#documents) for that state, or choose another address. `PUT /v1/company` returns the same code
as a [warning](#warnings), because the address can still be saved.

### `hazmat_destination`

Status `400` on `PUT /v1/orders/{orderId}/delivery-address`. On a quote or on `POST /v1/orders/batch`, the code is in `problems`. A hazardous product in the order cannot go to this address.

Remove the product from the order, or choose another address.

### `ship_to_restricted`

Status `400` on `PUT /v1/orders/{orderId}/delivery-address`. On a quote or on `POST /v1/orders/batch`, the code is in `problems`. The brand or distributor does not ship to this address.

Choose another address, or order from another supplier.

## Documents

### `document_locked`

Status `409`. The document was reviewed, and the company's status does not allow deleting it.

Keep the document. See [Documents](/companies/#documents).

### `document_already_uploaded`

Status `409`. The company already has this file.

Use the document the company already has.

### `file_too_large`

Status `413`. The file is larger than 30 MB.

Ask the user for a smaller file.

### `file_type_not_supported`

Status `415`. The file is not a PDF, PNG, JPEG, WebP, GIF, TIFF, HEIC, HEIF, or AVIF.

Ask the user for a file of one of these types.

## Product matching

### `reply_not_expected`

Status `409`. The product match is not waiting for a reply.

Read the match, and reply only when its status is `needs_reply`. See
[Answer a question](/product-matching/#answer-a-question).

## Orders

### `order_action_not_allowed`

Status `409`. The order's status does not allow this action.

Read the order, and offer only the actions its status allows. See [Change an order](/orders/#change-an-order).

### `supplier_refused_cancel`

Status `409`. The brand or distributor's system refused the cancel, and the order stays as it was. It may already have
shipped.

Tell the user the order could not be canceled. See [Cancel an order](/orders/#cancel-an-order).

### `order_total_changed`

Status `409`. A group differs from `expectedTotal` by $0.10 or more, for example because a price changed. Nothing was
created. `quote` has a fresh quote.

Show the new total to the user, then send the request again with the new `expectedTotal`.

### `order_has_problems`

Status `409`. A group or the company has a problem. Nothing was created. `quote` has a fresh quote that lists them, in
`problems` per group and in `companyProblems`.

Fix each problem, or leave that group out, then send the request again. A problem in `companyProblems` stops every group. See [Problems](/create-orders/#problems).

### `idempotency_key_reused`

Status `409`. The `Idempotency-Key` was already used with a different body.

Send a new key for a new request. Repeat a key only when you repeat the same request.

### `idempotency_key_in_use`

Status `409`. An earlier request with this `Idempotency-Key` is still finishing.

Try again shortly, with the same key and the same body.

## Webhooks

These appear in the salon app admin area. They are not API responses.

### `webhook_failed`

One delivery attempt failed. Beauty Router tries again for 24 hours.

Check that your webhook URL is reachable, checks the signature correctly, and responds in time. See
[Respond and retry](/webhooks/#respond-and-retry).

### `webhook_abandoned`

Beauty Router stopped trying to deliver an event after 24 hours.

Fix the webhook URL, then read what you missed. For orders, use `GET /v1/orders`. It takes a user token, so log in once per
company.

## Warnings

A warning comes in a `warnings` list on a successful response. Nothing failed, so the request does not need repeating.

### `email_mailbox_full`

`POST /v1/login`. The mailbox is full right now, so emails bounce until the user frees space.

### `email_temporary_address`

`POST /v1/login`. The address belongs to a disposable email service.

### `address_state_without_license`

`PUT /v1/company`. The address was saved, but the company has no license in that state. An order to that address fails
until the company has one. See [`address_state_without_license`](#address_state_without_license).