Getting Started with Prices
This guide walks you through creating and managing Price Specifications on the Hii Retail platform. By the end of this guide, you will understand how to set sales prices, purchase prices, and scheduled future prices for your Items.
Overview
What is a Price Specification?
A Price Specification is a structured value representing a monetary amount linked to an Item. It includes the price value, currency, validity period, and tax information.
Price Specifications enable:
- Sales prices for POS terminals
- Purchase prices for gross profit calculations
- Scheduled future price changes
- Price ranges with min/max limits
┌─────────────────┐
│ Item │
│ "Fanta Orange" │
└────────┬────────┘
│
│ has many
▼
┌─────────────────────────────────────────────────────────┐
│ Price Specifications │
├─────────────────┬─────────────────┬─────────────────────┤
│ SALES │ PURCHASE │ LOWEST_HISTORIC │
│ €14.99 │ €8.50 │ €12.99 │
│ (customer pays) │ (supplier cost) │ (for promotions) │
└─────────────────┴─────────────────┴─────────────────────┘
An Item must have at least one SALES Price Specification. This ensures POS systems can sell the Item and calculate margins correctly.
Price Types
| Type | Description | Use Case |
|---|---|---|
SALES | Regular sales price for customers | POS checkout, e-commerce |
PURCHASE | Cost price from supplier | Gross profit calculations, replenishment |
LOWEST_HISTORIC_PRICE | Lowest price in last 30 days | Required for advertised promotions (EU Directive 98/6/EC) |
Taxable Groups
Prices are linked to taxable groups that determine the VAT rate. Common options following European standards:
| Taxable Group | Description |
|---|---|
Standard | Standard VAT rate (e.g., 25% in Sweden) |
Reduced | Reduced VAT rate (e.g., 12% for food in Sweden) |
ReducedLow | Lower reduced rate |
SuperReduced | Super reduced rate |
Zero | Zero-rated goods |
Price Statuses
| Status | Description |
|---|---|
ACTIVE | Price is active and available for use |
DELETED | Price is deleted and should not be used |
Prerequisites
Before you begin, ensure you have:
- Items created: At least one Item to assign prices to (see Items guide)
- Business Units created: At least one Business Unit or Business Unit Group (see Business Units guide)
- Authentication Token: A valid JWT bearer token with the
pnp.price-spec.createpermission
For details on obtaining an access token, see the OAuth2 Authentication documentation.
API Base URL
All Price Specification Input API requests should be sent to:
https://price-specification-input.retailsvc.com/api/v2
Step 1: Create a Sales Price
Create a basic sales price for an Item at the Business Unit Group level. This price will propagate to all Business Units in the group.
Required Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for this price (max 250 characters) |
itemId | string | The Item this price belongs to |
type | string | SALES, PURCHASE, or LOWEST_HISTORIC_PRICE |
status | string | ACTIVE or DELETED |
value | number | The price amount (including tax) |
currencyId | string | ISO 4217 currency code (e.g., EUR, SEK, USD) |
validFrom | datetime | When the price becomes effective (ISO 8601 format) |
businessUnitGroupId | string | The Business Unit Group where this price applies |
Code Examples
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 's-5449000051578',
itemId: '5449000051578',
type: 'SALES',
status: 'ACTIVE',
value: 14.99,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
var payload = """
{
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "s-5449000051578",
itemId = "5449000051578",
type = "SALES",
status = "ACTIVE",
value = 14.99,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
Response
A successful request returns 202 Accepted.
The Price Specification Input API processes requests asynchronously. A 202 Accepted response means your request has been queued for processing.
Step 2: Create a Sales Price with Min/Max Limits
Add price limits to control what cashiers can charge. This is useful for items where the cashier may need to adjust the price within a defined range.
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"minPrice": 12.99,
"maxPrice": 17.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"minPrice": 12.99,
"maxPrice": 17.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 's-5449000051578',
itemId: '5449000051578',
type: 'SALES',
status: 'ACTIVE',
value: 14.99,
minPrice: 12.99,
maxPrice: 17.99,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
var payload = """
{
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"minPrice": 12.99,
"maxPrice": 17.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "s-5449000051578",
itemId = "5449000051578",
type = "SALES",
status = "ACTIVE",
value = 14.99,
minPrice = 12.99,
maxPrice = 17.99,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
Step 3: Create a Purchase Price
Purchase prices track what you pay suppliers. They're essential for gross profit calculations and replenishment systems.
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "p-5449000051578",
"itemId": "5449000051578",
"type": "PURCHASE",
"status": "ACTIVE",
"value": 8.50,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "p-5449000051578",
"itemId": "5449000051578",
"type": "PURCHASE",
"status": "ACTIVE",
"value": 8.50,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'p-5449000051578',
itemId: '5449000051578',
type: 'PURCHASE',
status: 'ACTIVE',
value: 8.50,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
var payload = """
{
"id": "p-5449000051578",
"itemId": "5449000051578",
"type": "PURCHASE",
"status": "ACTIVE",
"value": 8.50,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "p-5449000051578",
itemId = "5449000051578",
type = "PURCHASE",
status = "ACTIVE",
value = 8.50,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
With both a sales price (€14.99) and purchase price (€8.50), the system can calculate a gross profit of €6.49 (43.3% margin).
Step 4: Schedule a Future Price Change
Schedule a price change to take effect at a specific date and time in the future. The new price will automatically become active when validFrom is reached.
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "s-5449000051578-future",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 16.99,
"taxableGroupId": "Standard",
"validFrom": "2024-06-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "s-5449000051578-future",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 16.99,
"taxableGroupId": "Standard",
"validFrom": "2024-06-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 's-5449000051578-future',
itemId: '5449000051578',
type: 'SALES',
status: 'ACTIVE',
value: 16.99,
taxableGroupId: 'Standard',
validFrom: '2024-06-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
var payload = """
{
"id": "s-5449000051578-future",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 16.99,
"taxableGroupId": "Standard",
"validFrom": "2024-06-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "s-5449000051578-future",
itemId = "5449000051578",
type = "SALES",
status = "ACTIVE",
value = 16.99,
taxableGroupId = "Standard",
validFrom = "2024-06-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
Use a unique id for each price. A common convention is to prefix with the price type (s- for sales, p- for purchase) followed by the item ID and an optional suffix for versioning.
Step 5: Create a Lowest Historic Price
When running advertised promotions in the EU, you must display the lowest price from the last 30 days (EU Directive 98/6/EC).
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "lh-5449000051578",
"itemId": "5449000051578",
"type": "LOWEST_HISTORIC_PRICE",
"status": "ACTIVE",
"value": 12.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "lh-5449000051578",
"itemId": "5449000051578",
"type": "LOWEST_HISTORIC_PRICE",
"status": "ACTIVE",
"value": 12.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'lh-5449000051578',
itemId: '5449000051578',
type: 'LOWEST_HISTORIC_PRICE',
status: 'ACTIVE',
value: 12.99,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
var payload = """
{
"id": "lh-5449000051578",
"itemId": "5449000051578",
"type": "LOWEST_HISTORIC_PRICE",
"status": "ACTIVE",
"value": 12.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "lh-5449000051578",
itemId = "5449000051578",
type = "LOWEST_HISTORIC_PRICE",
status = "ACTIVE",
value = 12.99,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
The LOWEST_HISTORIC_PRICE is only required when the Item is part of an advertised price reduction. It's not required for regular markdowns or loyalty promotions.
Step 6: Create a Store-Specific Price
To create a price that only applies to a specific Business Unit (not inherited from a group), use the Business Unit endpoint.
- cURL
- Python
- Node.js
- Java
- .NET
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "s-5449000051578-store123",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 13.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitId": "store-123"
}'
response = requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "s-5449000051578-store123",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 13.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitId": "store-123"
}
)
const response = await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-price-specifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 's-5449000051578-store123',
itemId: '5449000051578',
type: 'SALES',
status: 'ACTIVE',
value: 13.99,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitId: 'store-123'
})
});
var payload = """
{
"id": "s-5449000051578-store123",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 13.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitId": "store-123"
}
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var payload = new {
id = "s-5449000051578-store123",
itemId = "5449000051578",
type = "SALES",
status = "ACTIVE",
value = 13.99,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitId = "store-123"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-price-specifications", content);
- Use
POST /api/v2/bu-g-price-specificationswithbusinessUnitGroupIdto create prices that propagate to all Business Units in the group - Use
POST /api/v2/bu-price-specificationswithbusinessUnitIdto create prices specific to a single Business Unit
Step 7: Update a Price
Use PATCH for partial updates. Note that id, itemId, validFrom, validTo, and businessUnitGroupId are immutable.
- cURL
- Python
- Node.js
- Java
- .NET
curl -X PATCH 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json-patch+json' \
-d '[
{"op": "replace", "path": "/value", "value": 15.99},
{"op": "replace", "path": "/maxPrice", "value": 18.99}
]'
response = requests.patch(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578",
params={"businessUnitGroupId": "acme-retail-group"},
headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json-patch+json"},
json=[
{"op": "replace", "path": "/value", "value": 15.99},
{"op": "replace", "path": "/maxPrice", "value": 18.99}
]
)
const response = await fetch(
'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group',
{
method: 'PATCH',
headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json-patch+json' },
body: JSON.stringify([
{ op: 'replace', path: '/value', value: 15.99 },
{ op: 'replace', path: '/maxPrice', value: 18.99 }
])
}
);
var operations = """
[{"op": "replace", "path": "/value", "value": 15.99},
{"op": "replace", "path": "/maxPrice", "value": 18.99}]
""";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json-patch+json")
.method("PATCH", HttpRequest.BodyPublishers.ofString(operations))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var operations = new[] {
new { op = "replace", path = "/value", value = 15.99 },
new { op = "replace", path = "/maxPrice", value = 18.99 }
};
var content = new StringContent(JsonSerializer.Serialize(operations), Encoding.UTF8, "application/json-patch+json");
var request = new HttpRequestMessage(HttpMethod.Patch,
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group") { Content = content };
var response = await httpClient.SendAsync(request);
The id, businessUnitGroupId, revision, itemId, validFrom, and validTo properties cannot be updated via PATCH. To change these, delete the price and create a new one.
Step 8: Delete a Price
Delete a price when it's no longer needed. By default, this performs a soft-delete (sets status to DELETED).
- cURL
- Python
- Node.js
- Java
- .NET
# Soft delete (default)
curl -X DELETE 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group' \
-H 'Authorization: Bearer <your-access-token>'
# Hard delete (permanent)
curl -X DELETE 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group&permanent=true' \
-H 'Authorization: Bearer <your-access-token>'
# Soft delete (default)
response = requests.delete(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578",
params={"businessUnitGroupId": "acme-retail-group"},
headers={"Authorization": f"Bearer {access_token}"}
)
# Hard delete (permanent)
response = requests.delete(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578",
params={"businessUnitGroupId": "acme-retail-group", "permanent": True},
headers={"Authorization": f"Bearer {access_token}"}
)
// Soft delete (default)
await fetch(
'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group',
{ method: 'DELETE', headers: { 'Authorization': `Bearer ${accessToken}` } }
);
// Hard delete (permanent)
await fetch(
'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group&permanent=true',
{ method: 'DELETE', headers: { 'Authorization': `Bearer ${accessToken}` } }
);
// Soft delete (default)
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group"))
.header("Authorization", "Bearer " + accessToken)
.DELETE()
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// Hard delete (permanent) - add &permanent=true to the URL
// Soft delete (default)
var response = await httpClient.DeleteAsync(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group");
// Hard delete (permanent)
var permanentResponse = await httpClient.DeleteAsync(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications/s-5449000051578?businessUnitGroupId=acme-retail-group&permanent=true");
Complete Pricing Example
Here's a complete example of setting up sales and purchase prices for an Item:
- cURL
- Python
- Node.js
- Java
- .NET
# 1. Create sales price
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"minPrice": 12.99,
"maxPrice": 17.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
# 2. Create purchase price
curl -X POST 'https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications' \
-H 'Authorization: Bearer <your-access-token>' \
-H 'Content-Type: application/json' \
-d '{
"id": "p-5449000051578",
"itemId": "5449000051578",
"type": "PURCHASE",
"status": "ACTIVE",
"value": 8.50,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}'
# 1. Create sales price
requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "s-5449000051578",
"itemId": "5449000051578",
"type": "SALES",
"status": "ACTIVE",
"value": 14.99,
"minPrice": 12.99,
"maxPrice": 17.99,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
# 2. Create purchase price
requests.post(
"https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications",
headers={"Authorization": f"Bearer {access_token}"},
json={
"id": "p-5449000051578",
"itemId": "5449000051578",
"type": "PURCHASE",
"status": "ACTIVE",
"value": 8.50,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
)
// 1. Create sales price
await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 's-5449000051578',
itemId: '5449000051578',
type: 'SALES',
status: 'ACTIVE',
value: 14.99,
minPrice: 12.99,
maxPrice: 17.99,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
// 2. Create purchase price
await fetch('https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications', {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 'p-5449000051578',
itemId: '5449000051578',
type: 'PURCHASE',
status: 'ACTIVE',
value: 8.50,
taxableGroupId: 'Standard',
validFrom: '2024-01-01T00:00:00Z',
currencyId: 'EUR',
businessUnitGroupId: 'acme-retail-group'
})
});
void createPrice(String id, String type, double value) throws Exception {
var payload = String.format("""
{
"id": "%s",
"itemId": "5449000051578",
"type": "%s",
"status": "ACTIVE",
"value": %.2f,
"taxableGroupId": "Standard",
"validFrom": "2024-01-01T00:00:00Z",
"currencyId": "EUR",
"businessUnitGroupId": "acme-retail-group"
}
""", id, type, value);
var request = HttpRequest.newBuilder()
.uri(URI.create("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications"))
.header("Authorization", "Bearer " + accessToken)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
// Create both prices
createPrice("s-5449000051578", "SALES", 14.99);
createPrice("p-5449000051578", "PURCHASE", 8.50);
async Task CreatePriceAsync(string id, string type, decimal value)
{
var payload = new {
id,
itemId = "5449000051578",
type,
status = "ACTIVE",
value,
taxableGroupId = "Standard",
validFrom = "2024-01-01T00:00:00Z",
currencyId = "EUR",
businessUnitGroupId = "acme-retail-group"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
await httpClient.PostAsync("https://price-specification-input.retailsvc.com/api/v2/bu-g-price-specifications", content);
}
// Create both prices
await CreatePriceAsync("s-5449000051578", "SALES", 14.99m);
await CreatePriceAsync("p-5449000051578", "PURCHASE", 8.50m);
Next Steps
Now that you can create Price Specifications, you can:
- Set up promotions: Create promotional prices linked to campaigns
- Configure tax rules: Set up taxable groups for different product categories
- Automate price updates: Build integrations to sync prices from your ERP system
Related Resources
- Price Specification Input API Reference
- Price Specification Concepts
- Prices Use Cases
- Items Guide
- Item Identifiers Guide
- Business Units Guide
Next: Tax - Learn how to configure tax regions and taxable groups for your items.