JTL Wawi
JTL Wawi is an ERP system designed for small and medium-sized businesses, especially those operating online stores. It integrates with multiple sales channels, manages inventory, orders, shipping, and offers financial reporting and customizability.
Features summary
The platform integration with JTL Wawi offers the following features:
- Search order: Allow consumers to find their order in the Returnless return form.
- Create return: Returns are processed directly within JTL Wawi. This feature is available in JTL Wawi 1.10.10 or later.
The integration with JTL Wawi is only available from version 1.9.0 and higher.
How to install
The connection with JTL Wawi is set up via the JTL Wawi API. In order for the Returnless platform to be able to reach the API, some steps are required.
Get a JTL API pilot program license
The API of JTL Wawi is currently in Open-Beta-Phase. This means a pilot program license is needed. To get this license, follow the steps provided in the Lizenz für JTL-Wawi API buchen guide.
Start API-REST server
Once you have arranged the API pilot program license, the API-REST server can be set up. To do so, follow the steps provided in the API-REST-Server starten guide.
In the API tool, select the correct profile. When setting the IP address, make sure to select the Lokale IP-Adresse des Rechners option. The port can be set to the default.
Expose the API
With the API server started, the API should be exposed so that other platforms outside of your JTL server are able to communicate with it. To do so, make sure the port you provided in the Start API-REST server step is made available to the network in the Firewall settings of your JTL server.
The API should be reachable via a URL. Make sure to save this URL as you will need it in the next step.
If you need more information regarding the REST API of JTL, we can also suggest to watch this video:
Connect your JTL Wawi to Returnless
With the API set up and exposed, the connection between Returnless and JTL Wawi can be set up. Follow the below steps:
-
In your JTL server, open the new interface (Beta) of JTL-Wawi. If you cannot find the icon on your desktop, open JTL-Wawi via the program path
C:/Program Files (x86)/JTL-Software/JTL-SharpWawi.exe.
-
Log in to the Returnless panel and navigate to Settings > Integrations page.

- Click on the Add new integration button in the e-commerce platform section.
- Select the JTL Wawi integration. A modal will open, which will guide you through the connection steps.!
- In step 1, specify a title and description for the integration. Also provide the API URL which you saved in the Expose the API step. Once provided, click next.jtl-wawi-step1.png
-
In step 2, the app registration flow is started. In JTL Wawi (Beta) you can open it by going to Admin > JTL Wawi API > App-Registrierungen.

By clicking on Hinzufugen > Weiter you should see the following screen:

-
Proceed to step 3 in Returnless. In JTL you will see the following screen:

-
When proceeding in JTL, the scopes will be shown. The required scopes are already marked for your convenience. The optional scopes can be enabled. We recommend to select all optional scopes so that your integration will contain all newest features when new features are added.

- Complete the steps in JTL Wawi. Once the JTL Wawi flow is completed, click on Verify integration in Returnless. The integration is now set up.
General settings
After the integration is set up, the version of your JTL Wawi is shown in the platform version setting. If this version is not shown, make sure to click on Refresh integration data.
How to use features
By default, all features will be disabled for the integration. Make sure to activate the features you wish to use.
Activate features
In order to start using a feature, make sure to enable the integration in a return form.
To view the feature settings, follow these steps:
- Login to your Return panel
- Navigate to Settings > Return forms and open the settings of the applicable return form.
- Go to the Integrations tab.
Here you will be able to define the default search integration and enable features.
Default search integration
Only a single integration will be used as the main source for the orders. If consumers need to look up the order in JTL Wawi, make sure to set this in the default search integration setting. Doing this will automatically enable the Search order feature in the integration features overview for the integration.

Enable features
Other features can be toggled in the same overview. Scroll down to the JTL Wawi section. Here you will see all available features and whether they are on or off. If you want to enable or disable a feature you can change it here and then click on Save.

Search order
only available with JTL Wawi version 1.9.0.0 and up
With the search order feature, consumers will be able to find their order in the Returnless return form by using their order number.
As the JTL Wawi integration does not have support for images yet, consumers will not be able to see product images in the return form when using this integration as the default search integration.
Search order settings
| Setting | Description | Options |
|---|---|---|
| Validation method | What field should the consumer fill in when looking up the order | Email address, Postal code |
| Order search field | Which field in JTL Wawi represents the order number that is known by the consumer. | External order number, Order number |
| Allowed item types | Which item types will be shown in the return form. The selected item types will be shown. Any item that does not have the given item type, will not be shown in the return form. | item (default), Blank, Shipping, Coupon , Voucher, Payment, Shipping surcharge, New customer coupon, Cash on Delivery, Shipping surcharge item, Packing, Gift for free, Trusted shops, Interest premium, Processing fee, Carton, Return delivery, Multi purpose voucher, Multi purpose voucher digital, Single purpose voucher, Single purpose voucher digital, Single purpose voucher redemption |
Create return
Important: When using JTL Wawi 1.10 in combination with fulfilment network, the create return action can trigger a bug in JTL Wawi that will cause a problem with syncing data between JTL Wawi and Fulfilment network. This issue has been resolved in JTL Wawi version 1.11. We strongly advise to update to JTL Wawi 1.11 before using the create return feature when also using fulfilment network.
To start using the create return feature, JTL Wawi 1.10.10.0 or later is required. If you previously connected your JTL Wawi with a version that is lower than 1.10.10, you need to set up the integration again so that the correct scope can be provided.
The create return feature creates a return in JTL for all items that have a Qty received that is higher than 0. When triggering the feature again, a new return will be created which does not consider the previously created return.
The created return will get status Announced and be linked to a Warehouse in JTL Wawi. To make sure the correct warehouse is linked, a mapping is provided.
The return reasons for each item in the return will be mapped to the return reasons in JTL Wawi. A mapping is provided in the settings to make sure the correct return reason is used.

Create return settings
| Setting | Description | Options |
|---|---|---|
| Default warehouse | The warehouse that should be passed to which the return is being sent as the default when the mapping is not set up. | A list of warehouses that have been set up in JTL Wawi |
| Default return reasons | Which return reason should be passed in the created return as the default when the mapping is not set up. | A list of return reasons that have been set up in JTL Wawi |
If the warehouses or return reasons in your JTL Wawi have changed, click Refresh integration data to fetch the current available warehouses and return reasons in JTL Wawi.
Mapping
It is possible to map a specific return address, return reason and return status to the counterpart in JTL Wawi. For this, a mapping is provided. If the mapping record is empty, the default setting is used as fallback.
Status update JTL > Returnless
With the status update feature, whenever a return statuses changes in JTL Wawi, the status of the associated return in Returnless will be updated. This is useful when you want to use JTL WMS for handling the package in the warehouse, but want to use Returnless to handle the refund flow. To use this feature, follow the steps below.
- Go to your platform integrations (Settings > integrations) and click on the JTL integration
- In the Mapping section, click on Return statuses and map assign which JTL status should be set to which Returnless status.
- Scroll down to the Webhook URL section. Here, a webhook URL is shown. Make sure to store this as you will need it again in step 7.
- Next, a workflow needs to be created in JTL Wawi. To do this, execute an SQL query in your JTL Wawi database. The query can be found below step 8.
- Open your JTL Wawi. In the top menu, navigate to Returns > Return status/Returns workflows

- In the overview, your return statuses are shown. For each return status, a workflow section exists. Click on the workflow section. Here you should see a workflow called GeneratedWebHook. Click on it.
- In the Actions section of the workflow, an event is shown (web request). Change the URL of that action to the Webhook URL you copied in step 3.
- Repeat step 6 and 7 for each return status that needs to be updated in Returnless as well.
Database query for step 3
IMPORTANT: this query is provided by JTL and should be considered as an example. Executing this query on your database is at your own risk.
Before executing the query, make sure a back-up is created of the database.
DELETE FROM dbo.tOptions
WHERE cKey = 'Workflow.WebhookUrl';
INSERT INTO dbo.tOptions (
cKey,
cValue
)
VALUES (
N'Workflow.WebhookUrl',
N'<URL>'
);
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'CustomWorkflows._CreateWorkflowForStatus') AND type IN (N'P', N'PC'))
DROP PROCEDURE CustomWorkflows._CreateWorkflowForStatus;
CREATE PROCEDURE CustomWorkflows._CreateWorkflowForStatus
@kRMStatus INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@nEvent INT,
@kWorkflow INT,
@XmlContent XML,
@nextPos INT;
SET @XmlContent = N'
<jtlAktion xmlns="jtlCore.Workflows.Aktionen"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:a="http://schemas.datacontract.org/2004/07/jtlCore.Workflows.Aktionen"
i:type="a:jtlAktionWebRequest">
<CancelOnError>false</CancelOnError>
<WawiVersion>1.10.12.0</WawiVersion>
<a:Parameters i:nil="true" />
<a:UseDotLiquidParameters>false</a:UseDotLiquidParameters>
<a:Body>{% capture query -%}
SELECT specversion,
type,
source,
id,
time,
datacontenttype,
apiVersion,
data
FROM CustomWorkflows.ReturnStatusUpdatedEvent
WHERE cRetoureNr = ''{{ Vorgang.Retourennummer }}''
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
{% endcapture -%}
{{ query | DirectQueryScalar }}</a:Body>
<a:Header>Content-Type: application/json</a:Header>
<a:Method>2</a:Method>
<a:NodePath />
<a:SetWert>false</a:SetWert>
<a:UriString>{% capture query -%}
SELECT cValue FROM dbo.tOptions WHERE cKey =''Workflow.WebhookUrl''
{% endcapture -%}
{{ query | DirectQueryScalar }}</a:UriString>
<a:UseDotLiquidBody>true</a:UseDotLiquidBody>
<a:UseDotLiquidHeader>true</a:UseDotLiquidHeader>
<a:UseDotLiquidUriString>true</a:UseDotLiquidUriString>
<a:WaitForResponse>false</a:WaitForResponse>
<a:WriteHeaderValues>false</a:WriteHeaderValues>
</jtlAktion>';
BEGIN TRY
BEGIN TRANSACTION;
-- 2.1 Determine or assign nEvent
SELECT @nEvent = rwf.nEvent
FROM dbo.tRMStatus AS s
JOIN dbo.tRMStatusWorkflow AS rwf
ON rwf.kRMStatus = s.kRMStatus
WHERE s.kRMStatus = @kRMStatus;
IF @nEvent IS NULL
BEGIN
SELECT @nEvent = ISNULL(MAX(nEvent), 0) + 1
FROM dbo.tRMStatusWorkflow;
END
-- 2.2 Early exit: existing webhook action?
SELECT TOP 1 @kWorkflow = rw.kWorkflow
FROM dbo.tRMStatusWorkflow AS rw
JOIN dbo.tWorkflowAktion AS wa
ON wa.kWorkflow = rw.kWorkflow
WHERE rw.kRMStatus = @kRMStatus
AND rw.nEvent = @nEvent
AND wa.cName = '#GeneratedWebHook#';
IF @kWorkflow IS NOT NULL
BEGIN
COMMIT TRANSACTION;
SELECT @kWorkflow AS kWorkflow;
RETURN;
END
-- 2.3 Insert into tWorkflow
INSERT INTO dbo.tWorkflow (
cName, nEvent, nObjekt, nVerknuepfung, nPos, nTyp, nApplikation,
nSchedulerOptions, dtSchedulerTime, nSchedulerHour, nSchedulerMinute,
nSchedulerDayValue, nSchedulerMonthValue
)
VALUES (
'CallWebhook',
@nEvent,
15,
0,
2,
0,
15,
0,
NULL,
0,
0,
0,
0
);
SET @kWorkflow = SCOPE_IDENTITY();
-- 2.4 Map status → workflow if new
IF NOT EXISTS (
SELECT 1
FROM dbo.tRMStatusWorkflow
WHERE kRMStatus = @kRMStatus
AND nEvent = @nEvent
AND kWorkflow = @kWorkflow
)
BEGIN
INSERT INTO dbo.tRMStatusWorkflow (
kRMStatus, kWorkflow, nTyp, nEvent
)
VALUES (
@kRMStatus,
@kWorkflow,
1,
@nEvent
);
END
-- 2.5 Determine next action position
SELECT @nextPos = ISNULL(MAX(nPos), -1) + 1
FROM dbo.tWorkflowAktion
WHERE kWorkflow = @kWorkflow;
-- 2.6 Insert the webhook action
INSERT INTO dbo.tWorkflowAktion (
kWorkflow, xXmlObjekt, nPos, cName
)
VALUES (
@kWorkflow,
@XmlContent,
@nextPos,
'#GeneratedWebHook#'
);
COMMIT TRANSACTION;
SELECT @kWorkflow AS kWorkflow;
RETURN;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW;
END CATCH
END;
IF OBJECT_ID('CustomWorkflows.ReturnStatusUpdatedEvent', 'V') IS NOT NULL
DROP VIEW CustomWorkflows.ReturnStatusUpdatedEvent;
CREATE VIEW CustomWorkflows.ReturnStatusUpdatedEvent
AS
SELECT
'1.0' AS specversion,
'de.jtl-software.retoure.status.updated' AS type,
'Wawi' AS source,
CAST(t.kRMRetoure AS VARCHAR(36)) AS id,
FORMAT(
SYSDATETIMEOFFSET(),
'yyyy-MM-dd''T''HH:mm:ss.fffK'
) AS time,
'application/json' AS datacontenttype,
'1' AS apiVersion,
JSON_QUERY(
(
SELECT
t2.kRMRetoure AS Id,
t2.kRMStatus AS StateId,
t2.kKunde AS CustomerId,
t2.cRetoureNr AS Number,
t2.cExternalNumber AS ExternalNumber
FROM dbo.tRMRetoure AS t2
WHERE t2.kRMRetoure = t.kRMRetoure
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
) AS data,
t.cRetoureNr AS cRetoureNr
FROM dbo.tRMRetoure AS t;
DECLARE @kRMStatus INT;
DECLARE status_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT kRMStatus
FROM dbo.tRMStatus
WHERE kRMStatus NOT IN (
SELECT RmStatus.kRMStatus
FROM dbo.tRMStatus AS RmStatus
LEFT JOIN dbo.tRMStatusWorkflow AS RmWorkflow
ON RmWorkflow.kRMStatus = RmStatus.kRMStatus
AND RmWorkflow.nTyp = 1
LEFT JOIN dbo.tWorkflow AS Workflow
ON Workflow.kWorkflow = RmWorkflow.kWorkflow
LEFT JOIN dbo.tWorkflowAktion AS Aktion
ON Aktion.kWorkflow = Workflow.kWorkflow
AND Aktion.cName = '#GeneratedWebHook#'
WHERE Aktion.cName IS NOT NULL
);
OPEN status_cursor;
FETCH NEXT FROM status_cursor INTO @kRMStatus;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC CustomWorkflows._CreateWorkflowForStatus @kRMStatus;
FETCH NEXT FROM status_cursor INTO @kRMStatus;
END
CLOSE status_cursor;
DEALLOCATE status_cursor;
IF OBJECT_ID('dbo.trg_RMStatus_AfterInsert', 'TR') IS NOT NULL
DROP TRIGGER dbo.trg_RMStatus_AfterInsert;
CREATE TRIGGER dbo.trg_RMStatus_AfterInsert
ON dbo.tRMStatus
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @kRMStatus INT;
DECLARE status_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT kRMStatus
FROM inserted;
OPEN status_cursor;
FETCH NEXT FROM status_cursor INTO @kRMStatus;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC CustomWorkflows._CreateWorkflowForStatus @kRMStatus;
FETCH NEXT FROM status_cursor INTO @kRMStatus;
END
CLOSE status_cursor;
DEALLOCATE status_cursor;
END;
Automatic refund of returns
In order for refunds to be automatically created for returns, a workflow can be set up in JTL Wawi. This workflow will create a refund for all returns that have been created by Returnless using the Create return action.
To set up the workflow, follow these steps which have been provided by JTL:
IMPORTANT: these queries have been provided by JTL and should be considered as an example. Executing the queries on your database is at your own risk.
Before executing the queries, make sure a back-up is created of the database.
- Execute query 1
USE [eazybusiness] GO /****** Object: StoredProcedure [CustomWorkflows].[spRetoureGutschreiben] Script Date: 12.12.2025 11:57:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [CustomWorkflows].[spRetoureGutschreiben] @kRMRetourePos INT AS BEGIN UPDATE dbo.tRMRetourePos SET dbo.tRMRetourePos.nGutschreiben = 1 WHERE dbo.tRMRetourePos.kRMRetourePos= @kRMRetourePos; END
- execute query 2
INSERT INTO CustomWorkflows.tWorkflowObjects ( nObjekt, cName, cPkColumn ) VALUES ( 14, -- nObjekt - int N'RetourenPos', -- cName - nvarchar(100) N'kRMRetourePos' -- cPkColumn - nvarchar(100) )
- Restart JTL-Wawi completely after running the SQL queries
- Navigate to Return Workflow Settings. In JTL-Wawi, go to Retoure > Retourenstatus / Retouren Workflow . Then, select the desired status (e.g., Eingetroffen or Erledigt).
- Click on the Workflow tab and create a new workflow. Define the trigger (status change) and add conditions if desired.
- Add the action to create an invoice under RetourenPosition
- Activate and Save the workflow





