Skip to content

Send products for matching

View as Markdown
POST
/product-matches
  • Production and sandbox. The token decides the environment.https://api.beautyrouter.com/v1/product-matches
curl --request POST \
--url https://api.beautyrouter.com/v1/product-matches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "products": [ { "externalId": "inv-10482", "name": "Amberlin bond shampoo liter", "barcode": "850012345678", "brand": "Amberlin", "size": "33.8 fl oz" }, { "externalId": "inv-10517", "name": "Jadewell 6N", "brand": "Jadewell", "details": "Hair color tube, dark natural blonde", "images": [ "https://app.example.com/uploads/inv-10517-front.jpg" ] } ] }'

Sends up to 500 products. Returns one match for each product, in the same order. The matches belong to the logged-in user’s company, and other companies’ matches are not visible.

externalId is unique within the company. Sending the same externalId again returns the existing match. The same externalId twice in one request fails with validation_failed. A product with a barcode can come back matched right away.

Media typeapplication/json
object
products
required
Array<object>
>= 1 items <= 500 items
object
externalId
required

Your ID for the product. Unique within the company, and at most once per request.

string
>= 1 characters <= 128 characters
name
required

The product name as your user typed it.

string
barcode
string
brand
string
size
string
details

Anything else that helps identify the product.

string
images

Up to 10 photos of the product, as HTTPS URLs that Beauty Router downloads.

Array<string>
<= 10 items

Examples

ExampleTwo products
{
"products": [
{
"externalId": "inv-10482",
"name": "Amberlin bond shampoo liter",
"barcode": "850012345678",
"brand": "Amberlin",
"size": "33.8 fl oz"
},
{
"externalId": "inv-10517",
"name": "Jadewell 6N",
"brand": "Jadewell",
"details": "Hair color tube, dark natural blonde",
"images": [
"https://app.example.com/uploads/inv-10517-front.jpg"
]
}
]
}

One match for each product.

Media typeapplication/json
object
data
required

One match for each product you sent.

Array<object>
object
id
required

The product match ID.

string
externalId
required

Your ID for the product. Unique within the company.

string
>= 1 characters <= 128 characters
status
required

in_review: Beauty Router is matching the product. needs_reply: Beauty Router needs more information, asked in question. matched: final, with productId.

string
Allowed values: in_review needs_reply matched
productId

The matched product ID. Only when status is matched.

string
question

What Beauty Router needs to know. Only when status is needs_reply.

string
createdAt
required
string format: date-time
updatedAt
required
string format: date-time

Examples

ExampleOne matched, one in review
{
"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": "in_review",
"createdAt": "2026-10-27T09:14:02Z",
"updatedAt": "2026-10-27T09:14:02Z"
}
]
}

validation_failed: a field is missing or has a wrong value. field names it.

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

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

invalid_user_token: the user token is missing or wrong. user_token_expired: the user token expired. Log the user in again with POST /v1/login.

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": "invalid_user_token",
"message": "The user token is missing or not valid."
}
}

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."
}
}