Returns

Integrating Returns

ItemReturnJob

An ItemReturnJob serves as a container for all potential ItemReturns associated with a placed Order. It encompasses all items eligible for return and tracks actual returned ItemReturns, including the returned items within them.

During interactions with the ItemReturnJob, validations ensure that only items purchased in the given order can be returned in the purchased quantities.

The ItemReturnJob presents the available returnable items along with a summary of returned items in a single easily readable line item.

Example:

{
   returnableLineItems: [
      {
        delivered: 5,
        returned: 3,
        returnable: 2,
        ...
      }
   ],
  ...
}

The values for returned and returnable are dynamically calculated, considering the included ItemReturns.

An ItemReturnJob is automatically generated through the designated Workflow after the Handover process. If the Handover Feature isn't utilized, the ItemReturnJob can be created via API.

All created ItemReturnJobs are accessible through this API call, with various filtering parameters available for refinement.

Alternatively, you can retrieve details of a specific ItemReturnJob via this API call.

To update the Status of an ItemReturnJob, utilize the ItemReturnJobStatusChangeAction API Action:

Once an ItemReturnJob is established, ItemReturns can be appended.

ItemReturn

An ItemReturn represents all items actually returned within the associated ItemReturnJob. It is imperative to have a valid ItemReturnJob before creating an ItemReturn.

While adding or updating an ItemReturn within an existing ItemReturnJob, item validations ensure that the returned quantity doesn't exceed the delivered and previously returned amounts.

To initiate the creation of a new ItemReturn, utilize the AddItemReturnAction API Action.

For updating an existing ItemReturn, utilize the following API Actions:

  • Change the Status via ItemReturnStatusChange

  • Replace items via ItemReturnReplaceReturnedLineItemsAction

  • Remove the ItemReturn from the ItemReturnJob using DeleteItemReturnAction

Returned item conditions

When accepting returned items, the condition of the items can be defined. In the Returns App, the default value for conditions is set to "not damaged". However, there is no default value defined in the back end.

Localized itemConditions can be added to the returnConfiguration via API. The translation depends on the locale of the user using this endpoint and the tenantLocaleConfiguration as a fallback.

A user of our API can use these predefined conditions or provide their own ones when creating or updating itemReturnLineItem of an ItemReturn. The localized condition can be provided like this example:

itemConditionLocalized = { de_DE: 'gefällt nicht', en_US: 'do not like' }

When getting this ItemReturn via REST oder GQL, you will receive an additional field called itemCondition which contains only the localized value. This translation depends on the users locale.

Return reasons should help our customers to specify why certain items have been returned by the customer while creating an ItemReturn. In order to get pre-defined return reasons, these reasons can be added to the given ReturnConfiguration (1)

These reasons can be passed while creating an ItemReturn through the API. Having default reasons is optional and not mandatory for passing reasons into an ItemReturn. (2)

Default values for return reasons in the backend are not provided; however, it is possible to manage them on the client side. Like we are doing it with our app by setting the default value for return reason to "no reason". If no additional reasons are specified through the backend, the return reasons will not be displayed.

Return Reasons

Adding predefined return reasons

You can add translatable availableReturnReasons to the returnConfiguration via API. The translation depends on the locale of the user using this endpoint and the tenantLocaleConfiguration as a fallback.

Using return reasons in ItemReturns

A user of our API can use this predefined return reasons or provide their own ones when creating or updating the ItemReturnLineItem of an ItemReturn. The localized return reason can be provided like this example:

localizedReason = { de_DE: 'Falsche Farbe', en_US: 'Wrong color' }

When getting this ItemReturn via REST oder GQL, you will receive an additional field called reason which contains only the localized value. This translation depends on the users locale.

Getting and setting these values via REST:

Integrating Returns with Events

The returns module offers a powerful yet flexible way to process incoming returns, mark the returned items, capture return reasons and item condition. Here we will show how you can process this information and which events come into play.

In order to receive notifications for new or updatedItemReturnJobs, you need to set up subscriptions for the event types ITEM_RETURN_JOB_CREATED and ITEM_RETURN_JOB_UPDATED. Please refer to the documentation on Eventing for detailed instructions on setting up subscriptions via the API.

Item Return Job is created

Once the handover process is completed, the platform automatically creates a new ItemReturnJob entity. You will receive a notification through the ITEM_RETURN_JOB_CREATED event.

The initial status of the ItemReturnJob is OPEN. The returnableLineItems array contains all items from the order that are eligible for return. Regardless of whether the order was split into multiple pick jobs, you will always be able to process all items from the entire order. The itemReturns array is empty as no items have been returned yet. Here's an example (some fields omitted for better readability):

ITEM_RETURN_JOB_CREATED
{
  "event": "ITEM_RETURN_JOB_CREATED",
  "payload": {
    "id": "460c860c-8dd0-4935-ad66-b38ae24149b8",
    "version": 1,
    "status": "OPEN",
    "processRef": "02104322-06a9-4055-8bab-e91e7a6e5db0",
    "tenantOrderId": "ORDER-1234",
    "shortId": "ER8",
    "originFacilityRefs": [
      "0ff83639-8e17-4f76-910a-20971968f103"
    ],
    "returnableLineItems": [
      {
        "id": "9266db8a-b412-41f0-93d3-9e1f0979e513",
        "delivered": 1,
        "returnable": 1,
        "returned": 0,
        "article": {
          "tenantArticleId": "TG560052",
          "title": "TechGlow Smartwatch Ultra",
          "imageUrl": "https://picsum.photos/id/0/5000/3333"
        }
      },
      {
        "id": "cbe81a6f-76c8-4e19-8e2e-89e875467102",
        "delivered": 1,
        "returnable": 1,
        "returned": 0,
        "article": {
          "tenantArticleId": "NT420074",
          "title": "NovaTech Smartphone 2000 Pro",
          "imageUrl": "https://picsum.photos/id/20/3670/2462"
        }
      }
    ],
    "itemReturns": []
  },
  "eventId": "ddee67fc-296f-4d22-bbf5-55cb4db02619"
}

The first return is processed and a new ItemReturn entity is created

Let's imagine the customer has sent back an item to the shop where the incoming return is now processed with the Returns App. Here's an example for the ITEM_RETURN_JOB_UPDATED event:

ITEM_RETURN_JOB_UPDATED
{
  "event": "ITEM_RETURN_JOB_UPDATED",
  "payload": {
    "id": "460c860c-8dd0-4935-ad66-b38ae24149b8",
    "version": 2,
    "status": "OPEN",
    "processRef": "02104322-06a9-4055-8bab-e91e7a6e5db0",
    "tenantOrderId": "ORDER-1234",
    "shortId": "ER8",
    "originFacilityRefs": [
      "0ff83639-8e17-4f76-910a-20971968f103"
    ],
    "returnableLineItems": [
      {
        "id": "9266db8a-b412-41f0-93d3-9e1f0979e513",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "TG560052",
          "title": "TechGlow Smartwatch Ultra",
          "imageUrl": "https://picsum.photos/id/0/5000/3333"
        }
      },
      {
        "id": "cbe81a6f-76c8-4e19-8e2e-89e875467102",
        "delivered": 1,
        "returnable": 1,
        "returned": 0,
        "article": {
          "tenantArticleId": "NT420074",
          "title": "NovaTech Smartphone 2000 Pro",
          "imageUrl": "https://picsum.photos/id/20/3670/2462"
        }
      }
    ],
    "itemReturns": [
      {
        "id": "0e3db3de-100b-49dc-b63d-c4a9e99ba5f5"
        "status": "FINISHED",
        "returnFacilityRef": "0ff83639-8e17-4f76-910a-20971968f103",
        "tenantOrderId": "ORDER-1234",
        "returnedLineItems": [
          {
            "id": "118da0bd-40ae-4c48-b3e7-189505ac4d7b",
            "status": "ACCEPTED",
            "tenantArticleId": "TG560052",
            "reasons": [
              {
                "reason": "Don't like product",
                "reasonLocalized": {
                  "de_DE": "Artikel gefällt nicht",
                  "en_US": "Don't like product"
                }
              }
            ],
            "itemReturnJobLineItemRefs": [
              "9266db8a-b412-41f0-93d3-9e1f0979e513"
            ]
          }
        ]
      }
    ]
  },
  "eventId": "d55e0435-c9fb-4003-bd2f-d23bcab5b5aa"
}

What you can observe in this example:

  • The returnableLineItems array reflects the updated values of the returnable and returned fields.

  • The itemReturns array contains the first ItemReturn with details about the returned items in the returnedLineItems array. The status of the ItemReturn is FINISHED because the process has been completed in the Returns app. For each returned item, there can be return reasons and comments, and an item condition based on your configuration. This will help you to capture individual reasons and quality levels for each returned line item. The status of the returned line item is ACCEPTED.

Another item is returned and a second ItemReturn is added

Continuing with our example, the customer has also returned the second item and the return was received and processed. The ITEM_RETURN_JOB_UPDATED event will include another ItemReturn in the itemReturns array:

ITEM_RETURN_JOB_UPDATED
{
  "event": "ITEM_RETURN_JOB_UPDATED",
  "payload": {
    "id": "460c860c-8dd0-4935-ad66-b38ae24149b8",
    "version": 3,
    "status": "OPEN",
    "processRef": "02104322-06a9-4055-8bab-e91e7a6e5db0",
    "tenantOrderId": "ORDER-1234",
    "shortId": "ER8",
    "originFacilityRefs": [
      "0ff83639-8e17-4f76-910a-20971968f103"
    ],
    "returnableLineItems": [
      {
        "id": "9266db8a-b412-41f0-93d3-9e1f0979e513",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "TG560052",
          "title": "TechGlow Smartwatch Ultra",
          "imageUrl": "https://picsum.photos/id/0/5000/3333"
        }
      },
      {
        "id": "cbe81a6f-76c8-4e19-8e2e-89e875467102",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "NT420074",
          "title": "NovaTech Smartphone 2000 Pro",
          "imageUrl": "https://picsum.photos/id/20/3670/2462"
        }
      }
    ],
    "itemReturns": [
      {
        "id": "0e3db3de-100b-49dc-b63d-c4a9e99ba5f5",
        "status": "FINISHED",
        "returnFacilityRef": "0ff83639-8e17-4f76-910a-20971968f103",
        "tenantOrderId": "ORDER-1234",
        "returnedLineItems": [
          {
            "id": "118da0bd-40ae-4c48-b3e7-189505ac4d7b",
            "status": "ACCEPTED",
            "tenantArticleId": "TG560052",
            "reasons": [
              {
                "reason": "Don't like product",
                "reasonLocalized": {
                  "de_DE": "Artikel gefällt nicht",
                  "en_US": "Don't like product"
                }
              }
            ],
            "itemReturnJobLineItemRefs": [
              "9266db8a-b412-41f0-93d3-9e1f0979e513"
            ]
          }
        ]
      },
      {
        "id": "62efdc92-d5b7-4d2f-b5ea-87d4627c5463",
        "status": "FINISHED",
        "returnFacilityRef": "694cdd6c-3d59-4c0e-a051-d8c5b716df07",
        "tenantOrderId": "ORDER-1234",
        "returnedLineItems": [
          {
            "id": "01a84fdf-217c-4402-8e79-1ec279af6ad2",
            "status": "ACCEPTED",
            "tenantArticleId": "NT420074",
            "reasons": [
              {
                "reason": "Wrong delivery",
                "reasonLocalized": {
                  "de_DE": "Falsch geliefert",
                  "en_US": "Wrong delivery"
                },
                "comment": "did not order this"
              }
            ]
            "itemReturnJobLineItemRefs": [
              "cbe81a6f-76c8-4e19-8e2e-89e875467102"
            ]
          }
        ]
      }
    ]
  },
  "eventId": "37617f83-1ebe-4f81-b974-c10ae4a63bf0"
}

What you should note here:

  • A second ItemReturn was added to the itemReturns array.

  • If you look closely, you will see that the second item return has a different returnFacilityRef. This is to show that it is possible to process returns in different facilities (e.g. customer returns one item in the shop and the other is sent back to central returns facility).

  • Already existing ItemReturns will not be changed - meaning, once an item has been processed you cannot remove it or change its quantity.

  • The second item in the returnableLineItems array has updated values for the returnable and returned fields.

Once all items have been returned (returnable = 0 for all returnableLineItems), processing additional returns is not possible.

Currently, the status of the ItemReturnJob does not automatically switch to FINISHED. This functionality is planned for future development. However, you can update the status through the API using the updateItemReturnJob call with FinishItemReturnJob payload. This action will trigger another ITEM_RETURN_JOB_UPDATED event.

ItemReturnLineItem status ACCEPTED/REJECTED

In the next example we will process a new order with different items. When processing the incoming return in the Returns app, the user can also request an additional quality check to be performed for the received goods. This functionality is particularly useful for high-valued goods that require a more thorough inspection of their quality.

These line items will have status of WAITING_FOR_INPUT as you can see in the example below:

ITEM_RETURN_JOB_UPDATED with status WAITING_FOR_INPUT
{
  "event": "ITEM_RETURN_JOB_UPDATED",
  "payload": {
    "id": "d2c0f718-88da-4067-949b-f2dc95d66057",
    "version": 2,
    "status": "OPEN",
    "processRef": "821a29f0-8d42-4dfa-bc91-4a112c4c62fb",
    "tenantOrderId": "ORDER-2222",
    "shortId": "DS4",
    "originFacilityRefs": [
      "aa89b8b2-ac83-4592-a36e-f4f77fde06dc"
    ],
    "returnableLineItems": [
      {
        "id": "201dde4e-adf3-4dc9-95c0-1669c47bbec0",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "CS0114141",
          "title": "CyberSense Wireless Mouse",
          "imageUrl": "https://picsum.photos/id/63/5000/2813"
        }
      }
    ],
    "itemReturns": [
      {
        "id": "ff0c2054-bbb0-4c58-9af9-84ea4b77f53b",
        "status": "FINISHED",
        "returnFacilityRef": "0ff83639-8e17-4f76-910a-20971968f103",
        "tenantOrderId": "ORDER-2222",
        "returnedLineItems": [
          {
            "id": "f338aac0-e996-4bb1-be55-82dbb19886fd",
            "status": "WAITING_FOR_INPUT",
            "tenantArticleId": "CS0114141",
            "reasons": [
              {
                "reason": "Damaged",
                "reasonLocalized": {
                  "de_DE": "Artikel beschädigt",
                  "en_US": "Damaged"
                }
              }
            ],
            "itemCondition": "Damaged",
            "itemConditionLocalized": {
              "de_DE": "Beschädigt",
              "en_US": "Damaged"
            },
            "itemReturnJobLineItemRefs": [
              "201dde4e-adf3-4dc9-95c0-1669c47bbec0"
            ]
          }
        ]
      }
    ]
  },
  "eventId": "a1be6f5f-d071-40eb-94f7-e87ce019631c"
}

Once the quality check has been performed, an item can either be accepted or rejected. This decision can be made through actions in the Backoffice or a corresponding mechanism. As a result, another ITEM_RETURN_JOB_UPDATED event will be triggered, and the status of the line item will be updated accordingly. For example, if a line item is rejected, the status will be REJECTED. Here's an example:

ITEM_RETURN_JOB_UPDATED with status REJECTED
{
  "event": "ITEM_RETURN_JOB_UPDATED",
  "payload": {
    "id": "d2c0f718-88da-4067-949b-f2dc95d66057",
    "version": 3,
    "status": "OPEN",
    "processRef": "821a29f0-8d42-4dfa-bc91-4a112c4c62fb",
    "tenantOrderId": "ORDER-2222",
    "shortId": "DS4",
    "originFacilityRefs": [
      "aa89b8b2-ac83-4592-a36e-f4f77fde06dc"
    ],
    "returnableLineItems": [
      {
        "id": "201dde4e-adf3-4dc9-95c0-1669c47bbec0",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "CS0114141",
          "title": "CyberSense Wireless Mouse",
          "imageUrl": "https://picsum.photos/id/63/5000/2813"
        }
      }
    ],
    "itemReturns": [
      {
        "id": "ff0c2054-bbb0-4c58-9af9-84ea4b77f53b",
        "status": "FINISHED",
        "returnFacilityRef": "0ff83639-8e17-4f76-910a-20971968f103",
        "tenantOrderId": "ORDER-2222",
        "returnedLineItems": [
          {
            "id": "f338aac0-e996-4bb1-be55-82dbb19886fd",
            "status": "REJECTED",
            "tenantArticleId": "CS0114141",
            "reasons": [
              {
                "reason": "Damaged",
                "reasonLocalized": {
                  "de_DE": "Artikel beschädigt",
                  "en_US": "Damaged"
                }
              }
            ],
            "itemCondition": "Damaged",
            "itemConditionLocalized": {
              "de_DE": "Beschädigt",
              "en_US": "Damaged"
            },
            "itemReturnJobLineItemRefs": [
              "201dde4e-adf3-4dc9-95c0-1669c47bbec0"
            ]
          }
        ]
      }
    ]
  },
  "eventId": "a0d7ef90-92ba-4aa3-a2c2-934a427aebc6"
}

Trigger Refund

The final example shows an ITEM_RETURN_JOB_UPDATED event that is triggered once a refund process has been started in the Backoffice or through a corresponding API call. Here you can see the details for the selected line item in the refund property:

ITEM_RETURN_JOB_UPDATED with refund
{
  "event": "ITEM_RETURN_JOB_UPDATED",
  "payload": {
    "id": "0f27dc34-1a5d-450d-8736-ad6b426ae360",
    "version": 6,
    "status": "OPEN",
    "processRef": "0cf08608-e82f-403a-a7d6-dd50d281f268",
    "tenantOrderId": "ORDER-3333",
    "shortId": "NT5",
    "originFacilityRefs": [
      "0ff83639-8e17-4f76-910a-20971968f103"
    ],
    "returnableLineItems": [
      {
        "id": "f00c0b11-d6be-4d35-881a-91ff3b0db162",
        "delivered": 1,
        "returnable": 0,
        "returned": 1,
        "article": {
          "tenantArticleId": "PP591833623",
          "title": "PowerPro USB Stick 512 GB",
          "imageUrl": "https://picsum.photos/id/17/2500/1667",
          "prices": [
            {
              "pricePerUnit": 49.95,
              "currency": "EUR"
            }
          ]
        }
      }
    ],
    "itemReturns": [
      {
        "id": "0e3db3de-100b-49dc-b63d-c4a9e99ba5f5",
        "status": "FINISHED",
        "returnFacilityRef": "0ff83639-8e17-4f76-910a-20971968f103",
        "tenantOrderId": "ORDER-3333",
        "returnedLineItems": [
          {
            "id": "7e08e8d3-3e56-4cb4-8ccd-7314172b96e0",
            "status": "ACCEPTED",
            "tenantArticleId": "PP591833623",
            "reasons": [
              {
                "reason": "Wrong delivery",
                "reasonLocalized": {
                  "de_DE": "Falsch geliefert",
                  "en_US": "Wrong delivery"
                }
              }
            ],
            "itemReturnJobLineItemRefs": [
              "f00c0b11-d6be-4d35-881a-91ff3b0db162"
            ],
            "refund": {
              "status": "CLOSED",
              "price": {
                "value": 49.95,
                "currency": "EUR"
              },
              "percent": null
            }
          }
        ]
      }
    ]
  },
  "eventId": "ecff2978-2c7d-4b11-801f-625ea8ff3494"
}

Summary

In your integration with the fulfillmenttools platform, you can evaluate the status of ItemReturns and ItemReturnLineItem to initiate the necessary follow-up processes. For example, you might need to start a refunding process or take other appropriate actions based on the order and return status. The availability of different status codes at each level assists you in performing the right actions for the order at the right time.

Fore more details and information, refer to the relevant sections of the API specification.

Last updated