curl --request POST \
--url https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests \
--header 'Authorization: Bearer <token>' \
--header 'x-tenant-id: <x-tenant-id>'import requests
url = "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests"
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-tenant-id': '<x-tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests', 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/connection-tests",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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"
"net/http"
"io"
)
func main() {
url := "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": 0,
"latencyMs": 123,
"shopVersion": "<string>",
"errorCode": "<string>",
"message": "<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>"
}
]
}Test Shop Connection
Runs a live connection and credentials test against a Wawi-managed webshop and reports the verdict. Mirrors the ‘Verbindung testen’ button of the WPF Verkaufskanalverwaltung. It contacts the shop with the stored synchronisation credentials and therefore validates reachability AND credentials in one call. Credentials are never accepted from the caller: they are read server-side from the shop record addressed by salesChannelId, so a caller can only test credentials that are already stored. Two properties are deliberate: (1) A completed test always answers HTTP 200, including when the shop is unreachable or rejects the credentials - an unreachable shop is a successful test with a negative verdict, reported through Status, not a failed request. No 502 and no 504 is therefore declared. (2) It is a POST behind saleschannels.write although its name suggests a read, because running the test updates the shop’s stored connection state on every call; callers should not poll it in a loop. The test is bounded by an internal timeout well below the platform request timeout, so a slow or unreachable shop returns Status = TimedOut rather than letting the platform timeout fire; there is no SSE, so the check is synchronous by design.
curl --request POST \
--url https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests \
--header 'Authorization: Bearer <token>' \
--header 'x-tenant-id: <x-tenant-id>'import requests
url = "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests"
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-tenant-id': '<x-tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests', 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/connection-tests",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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"
"net/http"
"io"
)
func main() {
url := "https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jtl-cloud.com/erp/v2/sales-channels/{salesChannelId}/shop/connection-tests")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"status": 0,
"latencyMs": 123,
"shopVersion": "<string>",
"errorCode": "<string>",
"message": "<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
Optional, client-generated key for deduplicating repeated write requests. A repeated request with the same key returns the originally recorded result instead of executing the effect again.
1 - 255The tenant ID for the target ERP instance.
Path Parameters
Sales channel id of the Wawi-managed shop whose connection is tested. 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.
Response
The connection test completed. The verdict is in the body - a 200 does NOT mean the shop was reachable or that the credentials were accepted; inspect Status. Status = Succeeded is the equivalent of the WPF IsAuthentificationValid flag.
Verdict of a completed connection test. Carries no credential and no part of one - not the value, not its length, not a hash.
The verdict. Status == Succeeded is the equivalent of the WPF IsAuthentificationValid flag. Note that REST transports this as the raw numeric enum value (the API registers no StringEnumConverter), while GraphQL renders it as SCREAMING_SNAKE_CASE.
0, 1, 2, 3, 4, 5, 6, 7 Wall-clock duration of the outbound test in milliseconds, measured by this endpoint around the call to the shop. Null when no call was attempted (Status = NotConfigured). Diagnostic only - not an SLA and not comparable across networks.
The shop's own version token as reported by its synchronisation interface, verbatim and unnormalized (the shop returns e.g. '503' for version 5.03). Null unless the shop got far enough to report one, which in practice means Status = Succeeded.
Stable machine-readable failure code, or null on success: shop-authentication-failed, shop-unreachable, shop-connection-timed-out, shop-incompatible-version, shop-invalid-response, shop-not-configured. Prefer this over parsing Message.
Human-readable, English, status-derived description of the failure, or null on success. Diagnostic only - not stable, not localized, and must not be parsed. Deliberately never the raw text the shop or the JTL license server returned.
Was this page helpful?