TikTok -Return and Refund - OLD
Summary of changes:
Date | Version | Changes | |
---|---|---|---|
27/06/2022 | 1.1 | Added some more details for Claim type = Return flow; | |
28/06/2022 | 1.2 | Added more info re rejection reasons; | |
TBD - claim status after 1st confirmation | |||
05/07/2022 | 1.3 | Return action default added; | |
Claim status after first confirmation = Completed; | |||
28/07/2022 | 1.4 | reverse_reject_reason_key Mapping added for this field |
|
29/07/2022 | 1.5 | Added column Hemi Claim Statuses; |
Mapping added: Hemi claim status to MP statuses; Claim status added into the description for reject case; Note removed; Typo corrected | | 09/08/2022 | | 1.6 | Edited the payment row. | | 10/08/2022 | | 1.7 | Scope edited as per abstraction based on a comment | | 16/08/2022 | | 1.8 | Based on a comment added info for reject reasons; Claim status clarifications/validations | | 17/08/2022 | | 1.9 | {Claim Status} added | | 19/08/2022 | | 2.0 | In claim status table, changed statuses with relevant one; Some typo corrected; | | 31/08/2022 | | 2.1 | Updates related to the reverse reason key logic; New field for storing Marketplace types of refund added | | 02/09/2022 | | 2.2 | MP types described to be visualized in more UF way | | 07/09/2022 | | 2.3 | Added reverse type=1 (Cancel) into the table; Added explanation for displaying MP statuses based on a bug | | 07/09/2022 | | 2.4 | Initiated by added | | 09/09/2022 | | 2.5 | Based on assumption added requirement for shipping cost | | 13/10/2023 | Bogomil Pavlov | v2.6 | Add “Refund Only Action Default” option |
We have 2 cases for return/refund management - pre-shipment & post-shipment.
Picture 1: Pre-shipment

Picture2: Post-shipment

Picture 3: Post-shipment ( the flow is similar to the flow “pre-shipment“)

As per described flows, we have similar steps when we create a claim, so based on this, we can incorporate into one cron pre & post shipment refunds. We will distinguish the pre & post shipment refunds using the reverse_type
which is returned into the response from Get Reverse Order List (will be described below in details).
We will use “Get Reverse Order List“ API call to get order_ids
for which buyer has requested refund. The order_ids
should be stored in Order Claim with related status (Will be mapped into the mapping table below).
<v2.6>Per account we can set by default to Accept or Reject refund; In Account TikTok table we will need to add additional options which will be Cancel Action Default, Return Action Default and Refund Only Action Default which will work as a default action if we would like to automatically accept or reject all claims for the specific account. If is “Accept“ , by default we accept the refund, if is “Reject“ , by default we reject the refund.
The diffent default action should work for claims with the following details
Claim type = Cancel + Marketplace type = ‘Request cancel’ - Cancel Action Default
Claim type = Cancel + Marketplace type = ‘Refund only’ - Refund Only Action Default
Claim type = Return - Return Action Default
<v/2.6>
We are able to reject or to confirm refund using separate API calls. Canceling or rejecting an order are irreversible actions. You cannot start again the order process for canceled and rejected orders. The refund request is per item line id and we can include each separate item as additional “refund“ node.
- Get Reverse Order List
Retrieve all reverse order requests from buyers
API Call: POST /api/reverse/reverse_order/list
API Docs: https://developers.tiktok-shops.com/documents/document/237498
Example Call:
{
"offset": 0,
"size": 20,
"update_time_from": 1527955200,
}
Call Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes |
---|---|---|---|---|
update_time_from |
timestamp | |||
Unix timestamp. Reverse order updated time. | We will use the Last Date Run and we will overlap by 5 minutes (Last Date Run - 5mins ) | |||
offset |
int32 |
Use this field to specify the offset of the order. Must be greater than or equal to 0.
If "offset" is less than 0, then "offset" is assigned the default value of 0. | Y | | N/A |
| size
| int32
Use this field to specify the maximum number of orders to obtain in a single page. Must be 1-100.
If "size" is less than 1, then "size" is assigned the default value of 10. If "size" is greater than 100, then "size" is assigned the default value of 100; | Y | | |
Example Response:
{
"code": 0,
"data": {
"more": true,
"reverse_list": [
{
"currency": "IDR",
"order_id": "576461302937453663",
"refund_total": "5000",
"return_item_list": [
{
"product_images": "",
"return_product_id": "",
"return_product_name": "",
"return_quantity": "",
"seller_sku": "",
"sku_id": "",
"sku_name": ""
}
],
"return_reason": "Package wasn't received",
"return_tracking_id": "E0h1y0j4l1F8G3U6X7p8",
"reverse_order_id": "4035225888722551903",
"reverse_record_list": [
{
"additional_image_list": "",
"additional_message": "I want to return",
"description": "",
"reason_text": "Package wasn't received",
"update_time": 1527955200
}
],
"reverse_request_time": 1527955200,
"reverse_status_value": 1,
"reverse_type": 2,
"reverse_update_time": 1527955200
}
]
},
"message": "Success",
"request_id": "202203070749000101890810281E8C70B7"
}
Mapping: New
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | ||
---|---|---|---|---|---|---|
reverse_list |
||||||
currency |
Currency for payment. | N/A | ||||
order_id |
The identification of a TikTok order | N/A | This will be the value, which we have already saved in Order > Marketplace Order ID. We need to use this one to find the order for which this claim is. | |||
refund_total |
Buyer refund total amount | N/A | ||||
return_item_list |
||||||
product_images |
N/A | |||||
return_product_id |
Reverse product id | N/A | As per confirmation from TT Returned Product ID is the same as Product ID which we will store in Channel Item ID AND further discussion with devs, we do not ; ****need to store this field in this case. | |||
return_product_name |
Reverse product name | N/A | ||||
return_quantity |
N/A | Here we should save order claim row to cover the returned quantity. |
Finding the order item by return_product_id
Only full quantity can be cancelled as per TT confirmation |
| | | seller_sku
| | | N/A | |
| | | sku_id
| SKU id | | N/A | N/A |
| | | sku_name
| | | N/A | |
| | return_reason
| | Buyer return reason. | | Order Claim >Marketplace Reason | |
| | return_tracking_id
| | | | Order Claim Rows > Tracking number | |
| | reverse_order_id
| | The identification of a TikTok reverse order | | Order Claim > Marketplace ID | |
| | reverse_record_list
| | | | | |
| | | additional_image_list
| Reverse additional images. | | N/A | |
| | | additional_message
| Reverse additional message. | | N/A | |
| | | description
| Reverse record description. | | N/A | |
| | | reason_text
| Reverse reason. | | N/A | |
| | | update_time
| Reverse record update time. | | N/A | |
| | reverse_request_time
| | | | Order Claim > Marketplace Date | |
| | reverse_status_value
| | Available value: INIT = 0;AFTERSALE_APPLYING = 1; AFTERSALE_REJECT_APPLICATION = 2;AFTERSALE_RETURNING = 3;AFTERSALE_BUYER_SHIPPED = 4; AFTERSALE_SELLER_REJECT_RECEIVE = 5;AFTERSALE_SUCCESS = 50; CANCEL_SUCCESS = 51;CLOSED = 99;COMPLETE = 100; | | Order Claim > Marketplace Status
AND
Order Claim > Claim Status | We need to store in Order Claim > Claim Status our internal status, based on the mapping table given below (Please see the column Hemi Claim Status)
We need to visualized into the interface via this way:
Init;
Aftersale Applying;
Aftersale Reject Application;
Aftersale Returning;
Aftersale Buyer Shipped;
Aftersale seller reject receive;
Aftersale Success;
Cancel Success;
Closed;
Completed; |
| | reverse_type
| | Filter by reverse type. Available value:
REFUND_ONLY = 2;
RETURN_AND_REFUND = 3;
REQUEST_CANCEL = 4; | | Order Claim > Type
AND
Order Claim> Marketplace type | Order claim with type, depending on received reverse_status, we will save Cancel and Return value as stated below:
REFUND_ONLY = 2 > Cancel
REQUEST_CANCEL = 4 > Cancel
RETURN_AND_REFUND = 3 > Return
Detailed explanation can be reviewed below into separate table
In regards to Marketplace type we would want to save in this new field following values:
Refund Only; Return and Refund;
Request Cancel;
This will be needed because during testing we have identified we cannot use the rejection reasons we have identified initially.
We need to visualized into the interface via this way:
(reverse_type = 1
) CANCEL= 'Cancel';
REFUND_ONLY= 'Refund only';
RETURN_AND_REFUND = 'Return and refund';
REQUEST_CANCEL = 'Request cancel'; |
| | reverse_update_time
| | | | N/A | |
Reverse types explanation:
TikTok Reverse Type | Hemi Type | Initiated By | Note |
---|---|---|---|
CANCEL = 1 | Cancel | Initiated by = Marketplace (this will be displayed when we have “Order canceled by system“) | |
Initiated by = Marketplace/Seller | Pre-shipment | ||
( this is for reverse_type=1 ) |
|||
REFUND_ONLY = 2 | Cancel | Initiated by = Buyer | Post-shipment. |
For this reverse type, once we send “Accept“ refund row should be automatically created. If we receive this reverse types, we will threat it as pre-shipment flow. | | REQUEST_CANCEL = 4 | Cancel | Initiated by = Buyer | Pre-shipment. For this reverse type, once we send “Accept“ refund row should be automatically created. If we receive this reverse types, we will threat it as pre-shipment flow. | | RETURN_AND_REFUND = 3 | Return | Initiated by = Buyer | Post-shipment.
For this reverse type we will have 2 steps for confirm/reject the request: The 1st confirmation: where we say we approve the return but we are not actually refunding the buyer until the product is returned into the seller warehouse and reviewed.
The 2nd confirmation: The refund row should not be created automatically after if we accept it! The refund row will be created after the second confirmation(after the product is returned successfully and the WH confirmed the product is in acceptable conditions.
If we receive this reverse type, we will threat it as post-shipment flow. |
Reverse status values mapping & Flow:
TikTok | TikTok Notes | Hemi Action & Hemi Status | Hemi Claim Status | Can be received for claim type: | Flow | Notes | |
---|---|---|---|---|---|---|---|
1 | INIT = 0 | Ignore, don't pay attention | N/A | N/A | N/A | N/A | We should skip such claims and not save them. As per TTs notes we will not receive this. |
2 | AFTERSALE_APPLYING = 1 | Return/refund request sent by buyer | Action = (depends on default value)+ Status = Pending | Created | Cancel & Return | If we get reverse order list and the reverse status is “AFTERSALE_APPLYING = 1“, this mean the buyer has requested return/refund. | |
So we will have claim, with status “Pending“ | |||||||
3 | AFTERSALE_REJECT_APPLICATION = 2 | Seller rejected return/refund request | Action = Reject + Status = Completed | Rejected | Cancel & Return | If we reject the reverse (Action = Reject, Status = Completed), the reverse status will be “AFTERSALE_REJECT_APPLICATION = 2 | |
4 | AFTERSALE_RETURNING = 3 | Seller approved return/refund request | Action = Accept + Status = Completed | 1. If Claim type = Cancel, the Claim status =Accepted & Refunded; | |||
2. If Claim type =Return, the Claim status =Accepted | Cancel & Return | Claim type = Cancel: |
If we confirm the reverse (Action = Accept & Status = Completed - refund row will be created;
Claim type = Return: If we confirm the reverse (Action = Accept & Status = Sent the reverse status will be “AFTERSALE_RETURNING = 3“ and this means we “allow“ the buyer to ship the goods back, BUT we will not create refund row at this stage (it will be created once from the WH confirms the products are in acceptable conditions) | | | 5 | AFTERSALE_BUYER_SHIPPED = 4 | Buyer has shipped the return | Action = Accept + Status = Completed | Accepted | Return | We will have: Action = Accept and Status=Sent | | | 6 | AFTERSALE_SELLER_REJECT_RECEIVE = 5 | Seller has rejected when it arrives at the warehouse | Action = Reject + Status = Completed | Rejected | Return | If the goods are NOT in acceptable condition, the status we will receive is AFTERSALE_SELLER_REJECT_RECEIVE = 5 , and this means we should reject the refund. | | | 7 | AFTERSALE_SUCCESS = 50 | Seller has accepted the return at the warehouse. | Action = Accept + Status = Completed | Accepted & Refunded | Return | If the goods are in acceptable condition, the status we will receive is AFTERSALE_SUCCESS = 50 and refund will be created. The refund should be completed! | | | 8 | CANCEL_SUCCESS = 51 | The buyer initiated a refund then cancelled it | Action = Reject + Status = Completed | Rejected | Cancel & Return | | final statuses | | 9 | CLOSED = 99 | The buyer initiated a refund then cancelled it | Action = Reject + Status = Completed | Rejected | Cancel & Return | | final statuses | | 10 | COMPLETE = 100 | The buyer initiated a refund then cancelled it | Action = Reject + Status = Completed | Accepted & Refunded | Cancel & Return | | final statuses |
(Based on Assumption): We would want to refund the shipping cost for pre-shipment refunds and respectively - to exclude the shipping cost for post-shipment refunds!
In other words, for:
-
Order Claim > Marketplace status = Request Cancel AND Cancel Include shipping cost into the refund amount!
-
Order Claim > Marketplace status = Return and Refund AND Refund only - Exclude shipping cost from the refund amount!
-
Confirm Reverse
Claim type = Cancel:
Note: This is also valid for the post-shipment refund only flow
Cron will pick the claim with Claim status = Created and will send the data to the MP.
If the acceptance from the Marketplace is “approved“ (Status = Complete + Claim Status=Accepted & Refunded), the cron will create a refund row with status completed and all relevant fields populated.
(Valid for Claim type = Return too) We need to make following validation here - If cron pick claim with claim status different from "Created", we need to save Error in Order error table. The error message should indicate the claim could not be proceeded, i.e “Claim cannot be proceed because the claim status is “{Claim Status}“ “
If we receive error during the confirmation step , the Status will be on “Error“ and refund row will not be created.
Claim type = Return:
Note: This is valid for the Return & Refund flow
- First Confirmation:
This would be the 1st confirmation, where we say we approve the return but we are not actually refunding the buyer until the product is returned into the seller warehouse and reviewed.
Cron will pick the claim with Claim status = Created.
The refund row should not be created automatically after this confirmation! The refund row will be created if we receive from WHs the products are in acceptable condition
If success we will set Status = Completed and Action = Accept +Claim Status= Accepted
If error, we will set Status = Error, Action = Accept & will store the error in Order Error table
The status of the claim after first confirmation should be completed
If we receive confirmation from the WH, that products are in good condition we will have the claim on status “Completed“ in order to be picked from the second confirmation and Order Payment with type= Refund on Status =Pending.
Note: From the refund pop-up , if we choose type Return, drop down field will appear and we need to select the claim to which we would want to refer the refund;
- Second confirmation:
Seller has accepted the return at the warehouse and the cron will pick the refunds with Status = Pending & Refund type = Return
After success, the order payment details record we will set on Status = Completed;
If error, the refund row will be set on Status = Error and need to store the error in Order Еrror table.**
API Call: POST /api/reverse/reverse_request/confirm
API Docs: https://developers.tiktok-shops.com/documents/document/237499
To confirm the refund, we should push reverse_order_id
Example Call:
{
"reverse_order_id": "4035225888722551903"
}
Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes |
---|---|---|---|---|
reverse_order_id | string | |||
The identification of a TikTok reverse order | Y | Order Claim > Marketplace ID |
Example Response:
{
"code": 0,
"message": "Success",
"request_id": "02162513172306500000000000000000000ffff0ae7f06cd26f48",
}
Possible Error codes & Messages:
Code | HTTP Code | Message |
---|---|---|
101000 | 400 | param is invalid |
102000 | 500 | internal service error |
204101 | 200 | order status is invalid |
- Reject Reverse
Claim type= Cancel:
Cron will pick the claim with status = Pending & Action= Reject and will send the data to the MP.
If we receive success , we need to set the Status = Complete and Action = Reject and Claim Status = Rejected
If we receive an error, we will have Status = Error & Action= Reject and we need to specify the exact error in Order Claim > Error field;
Claim type=Return:
First reject:
Cron will pick the claim with status = Pending & Action= Reject and will send the data to the MP.
If we receive success , we need to set the Status = Complete and Action = Reject and Claim Status = Rejected
If we receive an error, we will have Status = Error & Action= Reject and we need to specify the exact error in Order Claim > Error field;
No other actions requires if we reject the buyer request to return the products in WHs!
Second Reject:
The second reject will be required to be performed, when we have accepted the buyer request to return the products in WHs, BUT the goods were in bad condition (Order Claim > Marketplace Status = AFTERSALE_SELLER_REJECT_RECEIVE = 5 , so we would want to Reject the refund to buyer:

We will have Order Claim Status = Pending & Action = Reject
If we receive success , we need to set the Status = Complete and Action = Reject
If we receive an error, we will have Status = Error & Action= Reject and we need to specify the exact error in Order Claim > Error field;
API Call: POST /api/reverse/reverse_request/reject
API Docs: https://developers.tiktok-shops.com/documents/document/237497
Example Call:
{
"reverse_order_id": "4035225888722551903",
"reverse_reject_reason_key":"reverse_reject_request_reason_1",
"reverse_reject_comments": "Please return it"
}
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes |
---|---|---|---|---|
reverse_order_id |
The identification of a TikTok reverse order | Y | Order Claim > Marketplace ID | |
reverse_reject_reason_key |
The applicable reason keys for rejecting reverse order in different scenarios can be obtained from the "GetReverseReason" API: |
Reject cancel request (Seller reject buyer's cancel apply) --> [reverse_action_type= REQUEST_CANCEL_REFUND] & [reason_type=REJECT_APPLY] Reject refund-only request (Seller reject buyer's refund only apply) -->[reverse_action_type=REFUND]&[reason_type=REJECT_APPLY] Reject return & refund request (Seller reject buyer's return and refund apply) --> [reverse_action_type=RETURN_AND_REFUND] & [reason_type=REJECT_APPLY] Reject refund(Seller reject buyer's return parcel, when seller deems the returned parcel is unacceptable) --> [reason_type=REJECT_PARCEL] (no need to fill in the "reverse_action_type" field) | Y | Order Claim > Action Reason | If there is no reason filled, we will push the reasons below. Depends on the status of confirmation we have identified following reasons:
• For REFUND_ONLY = 2, which will be value stored into Order Claim > Marketplace type (Hemi type = Cancel) and Claim Status = Created we will hardcode and send this reason:
"reverse_reason_key": "seller_reject_apply_reason_is_unclear_or_lack_of_evidence"
• For REQUEST_CANCEL = 4, which will be value stored into Order Claim > Marketplace type (Hemi type = Cancel ) and Claim Status = Created we will hardcode and send this reason:
"reverse_reason_key": "order_manage_list_action_respond_popup_reject_reason_invalid_cancellation_reason_uk"
• For RETURN_AND_REFUND = 3, which will be value stored into Order Claim > Marketplace type (Hemi type = Return) & Claim Status = Accepted we will hardcode and send this reason: 'reverse_reject_return_parcel_reason_2_uk
' hardcode this reason for the second rejection;
Note that we need to save the used reason for information after sending the request if it was not filled in initially. |
| reverse_reject_comments
| The free comments for rejecting reverse order, limit 500 characters. | N | | |