External prices
How to manage prices via external services
Sometimes, you can decide not to manage prices within Commerce Layer but use an external service instead. You may want to do that in order to support more dynamic pricing or just leverage an existing service that you want to keep as your system of records.
If you want to use the external prices feature in a market, fill in the market's external_prices_url
field with your external service endpoint and make sure your service is compliant with the specifications described below.
Fetching external prices
When you add a line item to an order, set the _external_price
attribute to true
if you want the line item price to be provided by your external service, instead of Commerce Layer:
curl -g -X POST \
'https://yourdomain.commercelayer.io/api/line_items' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-H 'Content-Type: application/vnd.api+json' \
-d '{
"data": {
"type": "line_items",
"attributes": {
"quantity": 2,
"sku_code": "TSHIRTMM000000FFFFFFXLXX",
"_external_price": true
},
"relationships": {
"order": {
"data": {
"type": "orders",
"id": "QWERtyUpBa"
}
}
}
}
}'
Upon line item creation, Commerce Layer triggers a POST
request to the specified external_prices_url
endpoint, sending the line item payload (including the order) in the request body.
Request
The request payload is a JSON:API-compliant object you can query to perform your own computation. Aside from the target resource — line_items
in this specific case — some relationships are also included to avoid useless API roundtrips:
order
order.customer
order.customer.tags
order.line_items
order.market
item
{
"data": {
"id": "xYZkjABcde",
"type": "line_items",
"links": { ... },
"attributes": {
"quantity": 2,
"sku_code": "TSHIRTMM000000FFFFFFXLXX",
"_external_price": true
},
"relationships": { ... },
"meta": { ... }
},
"included": [
{
"id": "wBXVhKzrnq",
"type": "orders",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
},
{
"id": "bGvCXzYgNB",
"type": "customers",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
},
{
"id": "YawgnfmKad",
"type": "tags",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
},
{
"id": "hJnnKTGfRd",
"type": "line_items",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
},
{
"id": "DvlGRmhdgX",
"type": "markets",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
},
{
"id": "XGZwpOSrWL",
"type": "skus",
"links": { ... },
"attributes": { ... },
"relationships": { ... },
"meta": { ... }
}
]
}
In case the call to your external endpoint goes timeout, responds with an internal server error, or is blocked by the open circuit breaker, the API responds with a 422
status code by using the response error message. The circuit breaker internal counter (if closed) is incremented.
Response
Your service response (or error) must match the format described in the example below.
Example
The successful response must be a JSON object, returning at least the unit price computed by the external logic and the SKU code of the related product. If needed, you can optionally enrich the response with some additional information, notification messages, and metadata:
{
"success": true,
"data": {
"sku_code": "TSHIRTMM000000FFFFFFXLXX",
"unit_amount_cents": 4900,
"messages": [ ... ],
"metadata": {
"foo": "bar"
}
}
}
SKUs availability
When you fetch a list of SKUs with a sales channel, you only get those SKUs that have a price defined in the market's price list and at least a stock item in one of the market stock locations.
Security
When you activate external prices, a shared secret is generated at the market level. We recommend verifying the callback authenticity by signing the payload with that shared secret and comparing the result with the callback signature header.
Callbacks securityLast updated