Trendyol Returns Handle
Version | Date | Created / Updated | Notes |
---|---|---|---|
v1.0 | Hristiyan Georgiev | Initial version | |
v1.1 | 16/05/2025 | Hristiyan Georgiev | added mapping for Claim Status |
v1.2 | 16/06/2025 | Hristiyan Georgiev | cargoTrackingNumber mapping change |
Trendyol are sending us returns as claims where we have the option to accept or reject the return. There are seller initiated and Trendyol initiated returns. There are a few calls that we need to perform so they will be mentioned here.
We want to handle this by using our Claims functionality. All triggers, validations, etc. which are not mentioned here are as per our claims abstraction - Claims general management
The way claims are handled on Trendyol are as follows : we have one claim which can contain more than one product and then each quantity of this product has its unique id which then is used when accepting/rejecting a claim. In order to handle this properly within our system, we want to store store each product claim line as a separate claim. So if we have one claim with 5 claimItems
, we need to store them as 5 separate claims in MC Pro.
Get Returns
API Call: GET /integration/order/sellers/{sellerId}/claims?startDate=1717066748912
API Docs: https://developers.trendyol.com/int/docs/international-marketplace/international-return-flow-gulf/int-getClaims
The sellerId
we pick from Channel Trendyol
> Supplier ID
.
For startDate
we want to use the last_date_run
table. The first run will check for new claims in the last 7 days and afterwards we will get the date from last_date_run
table and filter claims using the paremeter. We want to overlap the time with 1 hour, meaning that we should use the time of last_date_run
- 1 hour.
Example response :
{
"totalElements": 1,
"totalPages": 1,
"page": 0,
"size": 1,
"content": [
{
"id": "b929332f-5f04-48b8-98b3-b5f23bd6c1a9",
"orderNumber": "604680279",
"orderDate": 1717066270423,
"customerFirstName": "order",
"customerLastName": "platform",
"claimDate": 1717066748912,
"cargoTrackingNumber": 50440236394,
"cargoProviderName": "",
"cargoSenderNumber": "50440236394"
"orderShipmentPackageId": 58406301,
"replacementOutboundpackageinfo": {
"cargoTrackingNumber": 72602420957047272632,
"cargoProviderName": "Aras Kargo Marketplace",
"cargoSenderNumber": "733861966410",
"cargoTrackingLink": "https://kargotakip.araskargo.com.tr/mainpage.aspx?code=90909090909",
"packageid": 28717254,
"items": [
"b71461e3-d1a0-4c1d-9a6d-18ecbcb5432d"
]
},
"rejectedpackageinfo": {
"cargoTrackingNumber": 72602420957047272632,
"cargoSenderNumber": "12345754875355",
"cargoProviderName": "Aras Kargo Marketplace",
"cargoTrackingLink": "https://kargotakip.araskargo.com.tr/mainpage.aspx?code=90909090909",
"packageid": 28717254,
"shipmentAddress": {
"address1": "xyz",
"address2": "xyz",
"city": "xyz",
"district": "xyz",
"phone": "123456789"
},
"items": [
{
"orderLine": {
"id": 7026397,
"productName": "Name921c4712-9f52-4087-bfd5-025b44137934 ProductCode2b08960f-c6ed-429c-8286-754adb23b7f8, one size",
"barcode": "88525201",
"merchantSku": "TY-Test53",
"productColor": "",
"productSize": "",
"price": 77.5,
"vatBaseAmount": 29824,
"salesCampaignId": 30661,
"productCategory": "Name227b64b4-e1fe-4dbd-adc6-fcb0f5579df3",
"lineItems": null
},
"claimItems": [
{
"id": "d32f5969-b49e-47fd-8022-aab017753cd0",
"orderLineItemId": 51881138,
"customerClaimItemReason": {
"id": 2019,
"name": "Undelivered International Shipment",
"externalReasonId": 2019,
"code": "UNDELIVEREDINT"
},
"trendyolClaimItemReason": {
"id": 2019,
"name": "Undelivered International Shipment",
"externalReasonId": 2019,
"code": "UNDELIVEREDINT"
},
"claimItemStatus": {
"name": "Accepted"
},
"note": "",
"resolved": true,
"autoAccepted": null,
"acceptedBySeller": false
},
{
"id": "898e5068-886a-4224-bb18-ccd3a9316eb3",
"orderLineItemId": 51881137,
"customerClaimItemReason": {
"id": 2019,
"name": "Undelivered International Shipment",
"externalReasonId": 2019,
"code": "UNDELIVEREDINT"
},
"trendyolClaimItemReason": {
"id": 2019,
"name": "Undelivered International Shipment",
"externalReasonId": 2019,
"code": "UNDELIVEREDINT"
},
"claimItemStatus": {
"name": "Accepted"
},
"note": "",
"resolved": true,
"autoAccepted": null,
"acceptedBySeller": false
}
]
}
]
},
"lastModifiedDate": 1717066749348,
"orderOutboundPackageId": null
}
]
}
Response Mapping :
Trendyol Field | MC Pro Field | Notes | ||||
---|---|---|---|---|---|---|
totalElements |
N/A | |||||
totalPages |
N/A | We need to implement pagination logic if there is more than one page. | ||||
page |
N/A | |||||
size |
N/A | |||||
content |
||||||
id |
Order Claim Row > Tracking Number |
This is not the tracking number but we need it when rejecting/accepting the return so we need to store it. This is the ID of the line and when rejecting/accepting the claim. | ||||
orderNumber |
We use this to map and find out which order the claim is for. This will be our Orders > Marketplace Order ID |
|||||
orderDate |
N/A | |||||
customerFirstName |
N/A | |||||
customerLastName |
N/A | |||||
claimDate |
Order Claim > Marketplace Date |
|||||
<v1.2>cargoTrackingNumber |
Order Claim Shipping Info > Tracking Number </v1.2> |
|||||
cargoProviderName |
Order Claim Shipping Info > Name |
|||||
cargoSenderNumber |
N/A | |||||
orderShipmentPackageId |
Order Claim Shipping Info > Case ID |
|||||
replacementOutboundpackageinfo |
Based on this object we will understand if the request is a Return or Exchange. In the 99% of the cases this object will be missing in the payload, in which case we need to store the claim with Order Claim > Type = Return. |
|||||
If we have this object, this means there is a replacement and we need to store the Order Claim > Type = Exchange |
||||||
cargoTrackingNumber |
||||||
<1.2>N/A</v1.2> | ||||||
cargoProviderName |
N/A | |||||
cargoSenderNumber |
N/A | |||||
cargoTrackingLink |
N/A | |||||
packageid |
Product In Order Line > Package ID |
We need to overwrite it as we will already have info filled in this field. | ||||
items |
We need to map this with the claimItems > id which is part of the items object of the get claim response. By this we can find out which item we need to exchange. |
|||||
rejectedpackageinfo |
||||||
cargoTrackingNumber |
N/A | |||||
cargoSenderNumber |
N/A | |||||
cargoProviderName |
N/A | |||||
cargoTrackingLink |
N/A | |||||
packageid |
N/A | |||||
shipmentAddress |
||||||
address1 |
N/A | |||||
address2 |
N/A | |||||
city |
N/A | |||||
district |
N/A | |||||
phone |
N/A | |||||
items |
||||||
orderLine |
||||||
id |
We map this with Product In Order > Order Item Line ID to understand which product is being returned. We then create a record for it in Order Claim Row . |
|||||
productName |
N/A | |||||
barcode |
N/A | |||||
merchantSku |
N/A | |||||
productColor |
N/A | |||||
productSize |
N/A | |||||
price |
N/A | |||||
vatBaseAmount |
N/A | |||||
salesCampaignId |
N/A | |||||
productCategory |
N/A | |||||
lineItems |
N/A | |||||
claimItems |
||||||
id |
Order Claim > Marketplace ID |
|||||
orderLineItemId |
N/A | |||||
customerClaimItemReason |
||||||
id |
N/A | |||||
name |
N/A | |||||
externalReasonId |
N/A | |||||
code |
N/A | |||||
trendyolClaimItemReason |
||||||
id |
N/A | |||||
name |
Order Claim > Marketplace Reason |
|||||
externalReasonId |
N/A | |||||
code |
N/A | |||||
claimItemStatus |
||||||
name |
Order Claim > Marketplace Status |
AND
<v1.1>Order Claim
> Claim Status
| Mapping for Claim Status
as follows :
-Created we map with “Created”
-WaitingInAction we map with “Created”
-Accepted we map with “Accepted & Refunded”.
-Cancelled we map with “Rejected”
-Rejected we map with “Rejected”
-Unresolved we map with “Created”
-InAnalysis we map with “Created” </v1.1> |
| | | | note
| | N/A | |
| | | | resolved
| | N/A | |
| | | | autoAccepted
| | N/A | |
| | | | acceptedBySeller
| | N/A | |
| lastModifiedDate
| | | | | N/A | |
| orderOutboundPackageId
| | | | | N/A | |
Any error response we can’t store in the system as we wouldn’t know which order it is, but we want to to display the error in the terminal when run with DEVMODETRUE.
After we have successfully stored the return request we will have two options : to approve or reject it.
Approve Return
API Call : PUT /integration/order/sellers/{sellerId}/claims/{claimId}/items/approve
The sellerId
we pick from Channel Trendyol
> Supplier ID
.
The claimId
we have to pick from Order Claim Row
> Tracking Number
Example call :
{
"claimLineItemIdList": [
"f9da2317-876b-4b86-b8f7-0535c3b65731"
],
"params": {}
}
Mapping :
Trendyol Field | MCPro Field | Notes |
---|---|---|
claimLineItemIdList |
Order Claim > Marketplace ID |
|
params |
N/A |
Sample Success Response : 200 OK
Sample Error Response :
{
"timestamp": 1743061507151,
"exception": "DomainNotFoundException",
"errors": [
{
"key": "leave.at.customer.threshold.not.found",
"message": "StoreFront 36 Currency TRY için eşik değeri bulunamadı.",
"errorCode": "",
"args": [
"36",
"TRY"
]
}
]
}
From the error response we want to map and store any errors
> message
in Order Errors
with Type
= Claim Accept.
Reject Return
Return rejection is currently out of scope so any reject action should not do anything at the moment.