curl --request PUT \
--url https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-tenant-id: <x-tenant-id>' \
--data '
{
"currencies": [
{
"currencyCode": "<string>",
"isDefault": true
}
]
}
'import requests
url = "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies"
payload = { "currencies": [
{
"currencyCode": "<string>",
"isDefault": True
}
] }
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'x-tenant-id': '<x-tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({currencies: [{currencyCode: '<string>', isDefault: true}]})
};
fetch('https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'currencies' => [
[
'currencyCode' => '<string>',
'isDefault' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-tenant-id: <x-tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies"
payload := strings.NewReader("{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"currencies": [
{
"currencyCode": "<string>",
"isDefault": true,
"name": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}Declaratively replaces the complete set of currencies assigned to a shop.
Declaratively replaces the complete set of currencies assigned to a shop. The request describes the full desired state - every currency contained in it is assigned and every currency not contained in it is unassigned. The call is therefore idempotent: repeating it with the same body leaves the shop in the same state, and because the currency is addressed by its natural code (ADR-85) rather than by a server-generated surrogate, no clientId or request token is needed to make a retry safe. Exactly one assignment must be marked as the default currency, and the list must not be empty - a shop without any currency cannot price anything, so clearing all assignments is not an accepted target state on this route. Note on the response shape: unlike a command that returns only the minimal necessary data, this one echoes the complete resulting assignment list. That is deliberate - it matches the existing sales channel precedent and the declarative-replace example in ADR-57, and it saves the caller a follow-up read to learn the canonical form and resolved display name of the codes it just submitted. Concurrency: this write is last-writer-wins. It takes no If-Match header and no row version, so two concurrent calls for the same shop overwrite each other without a conflict being reported - the second call simply wins. Callers that need to protect a read-modify-write cycle have to coordinate outside this API. This is a deliberate choice for the first release of the endpoint, not an oversight: the underlying column (bRowversion) is not mapped today, and adding a required precondition later would be a breaking change, so it is called out here rather than left implicit.
curl --request PUT \
--url https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-tenant-id: <x-tenant-id>' \
--data '
{
"currencies": [
{
"currencyCode": "<string>",
"isDefault": true
}
]
}
'import requests
url = "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies"
payload = { "currencies": [
{
"currencyCode": "<string>",
"isDefault": True
}
] }
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'x-tenant-id': '<x-tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({currencies: [{currencyCode: '<string>', isDefault: true}]})
};
fetch('https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'currencies' => [
[
'currencyCode' => '<string>',
'isDefault' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-tenant-id: <x-tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies"
payload := strings.NewReader("{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/currencies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currencies\": [\n {\n \"currencyCode\": \"<string>\",\n \"isDefault\": true\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"currencies": [
{
"currencyCode": "<string>",
"isDefault": true,
"name": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}{
"type": "https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"instance": "/api/route",
"traceId": "0HMPNHL0JHL76:00000001",
"detail": "<string>",
"errors": [
{
"name": "Error or field name",
"reason": "Error reason",
"code": "<string>",
"severity": "<string>"
}
]
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Headers
The tenant ID for the target ERP instance.
Path Parameters
Sales channel id of the shop whose currencies are replaced. This is a tenant-local, composite identifier and not a UUID (ADR-69) - it is opaque to the caller and must be taken verbatim from a sales channel listing; the internal shop key (kShop) is never accepted here.
Body
Request model for SaveShopCurrencies command endpoint. Route parameters bind from the route, query parameters from the query string, everything else from the body.
The complete desired set of currencies for the shop. Any currency currently assigned but not contained in this list is unassigned. Must contain at least one entry, exactly one of which is marked as the default.
Show child attributes
Show child attributes
Response
Successfully replaced the shop currencies. Returns the resulting assignments with their canonical codes and resolved display names.
Declaratively replaces the complete set of currencies assigned to a shop. The request describes the full desired state - every currency contained in it is assigned and every currency not contained in it is unassigned. The call is therefore idempotent: repeating it with the same body leaves the shop in the same state, and because the currency is addressed by its natural code (ADR-85) rather than by a server-generated surrogate, no clientId or request token is needed to make a retry safe. Exactly one assignment must be marked as the default currency, and the list must not be empty - a shop without any currency cannot price anything, so clearing all assignments is not an accepted target state on this route. Note on the response shape: unlike a command that returns only the minimal necessary data, this one echoes the complete resulting assignment list. That is deliberate - it matches the existing sales channel precedent and the declarative-replace example in ADR-57, and it saves the caller a follow-up read to learn the canonical form and resolved display name of the codes it just submitted. Concurrency: this write is last-writer-wins. It takes no If-Match header and no row version, so two concurrent calls for the same shop overwrite each other without a conflict being reported - the second call simply wins. Callers that need to protect a read-modify-write cycle have to coordinate outside this API. This is a deliberate choice for the first release of the endpoint, not an oversight: the underlying column (bRowversion) is not mapped today, and adding a required precondition later would be a breaking change, so it is called out here rather than left implicit. - Response
The persisted currency assignments, in the order submitted, with each code normalized to its canonical form and its display name resolved from the Wawi currency master data.
Show child attributes
Show child attributes
Was this page helpful?