TikTok - Ship Orders
Summary of changes:
Version | Date | Created / Updated | Notes |
---|---|---|---|
v1.1 | 20.06.2024 | Hristiyan Georgiev | TikTok has new API version and updates. The scope was also updated to the latest changes on TikTok. Everything that is not tagged with v1.1 remains the same. |
v1.2 | 6.01.2025 | Hristiyan Georgiev | Added additional error response and handling |
v1.3 | 23.01.2025 | Hristiyan | Added new call and logic for shipping. |
The purpose of this page is to give good understanding of the TikTok’s shippment logic.
<v1.1>
To ship order on TikTok, first we should get & store all the available couriers for TikTok because it is mandatory when shipping an order to push shipping_provider_id
. We are not able to ship with provider which is not part of the TikTok shipping provider list!
For us to successfully ship an order, we need to have the correct shipping providers from TikTok, but in order to get those providers, we need to first find out which are the delivery options and then based on that get the shipping providers. There are two separate calls for that.
Get delivery options
This API is used to obtain the list of Delivery options subscribed by the seller's designated warehouse. We need to have it in order to download all possible couriers and then do mapping, set default couriers etc. based on those TikTok Couriers. Basically this call can be incorporated with the Get Shipping providers call and could be our first step.
We want to truncate the table before we call and then freshly store all the available delivery options. We want to do that in order to avoid missing some new/removed delivery options.
API Call : GET /logistics/202309/warehouses/{warehouse_id}/delivery_options
API Docs : https://partner.tiktokshop.com/docv2/page/650aa46ebace3e02b75d9afa?external_id=650aa46ebace3e02b75d9afa
We need to pass the shop_cipher
as query property which was obtained with the Get Authorised Shops call found here TikTok - Authentication & Database structure
warehouse_id
is taken from Location TikTok
> Warehouse ID
Execute the call for every Account Location
. Location TikTok
is connected to the Account
through Account Location → Location → Location TikTok
.
Example call :
https://open-api.tiktokglobalshop.com/logistics/202309/warehouses/7000714532876273410/delivery_options?app_key=123abc&sign=5361235029d141222525e303d742f9e38aea052d10896d3197ab9d6233730b8c×tamp=1625484268&shop_cipher=ROW_RHkDDABBAAB8tKAVoAqsMTjsQZFLyNfY
Example response :
{
"code": 0,
"data": {
"delivery_options": [
{
"description": "send by seller services.",
"dimension_limit": {
"max_height": 0,
"max_length": 0,
"max_width": 0,
"unit": "CM"
},
"id": "6956548250505578241",
"name": "ecom_logistics_type_SOF",
"type": "SEND_BY_SELLER",
"weight_limit": {
"max_weight": 0,
"min_weight": 0,
"unit": "GRAM"
}
},
{
"description": "LSV-DS-UK-Std",
"dimension_limit": {
"max_height": 120,
"max_length": 120,
"max_width": 120,
"unit": "CM"
},
"id": "7021054158430013190",
"name": "ecom_logistics_type_Standard",
"type": "STANDARD",
"weight_limit": {
"max_weight": 15000,
"min_weight": 0,
"unit": "GRAM"
}
}
]
},
"message": "Success",
"request_id": "202406271539596AFC13A540D7110209C0"
}
Response mapping :
TikTok Field | Hemi Mapping | Comments | |||
---|---|---|---|---|---|
code |
N/A | ||||
data |
N/A | ||||
delivery_options |
N/A | ||||
description |
TikTok Delivery Options > Description |
New table suggested. This should be slave table of Account TikTok |
|||
dimension_limit |
N/A | ||||
max_height |
N/A | ||||
max_length |
N/A | ||||
max_width |
N/A | ||||
unit |
N/A | ||||
id |
TikTok Delivery Optoins > Delivery Option ID |
Note! It is possible to have more than one option so we need to be able to store them all and then use them all when doing the Get Shipping Providers call. | |||
name |
N/A | ||||
type |
N/A | ||||
weight_limit |
N/A | ||||
max_weight |
N/A | ||||
min_weight |
N/A | ||||
unit |
N/A | ||||
message |
N/A | ||||
request_id |
N/A |
Since we cannot associate this call with any order or product, we cannot store an error but we want to be able to see the error when cron is run from the terminal with DEVMODETRUE.
After we have the delivery option ids, we are ready to get the shipping providers with the following call :
Get Shipping Providers
This API is used to obtain the shipping provider corresponding to the specified delivery option. We can have many delivery options so we need to call each one of them and store the different couriers across different delivery option ids.
Using this call, we will need to store the shipping carriers provided from TikTok - will be stored into Courier
table. We would want to map the shipping provider name but to send the shipping provider id to TikTok MPs. We will have courier mapping so we can map the respective TikTok courier to what we have in Hemi set as courier.
If TikTok add or remove some couriers, we want to respectively add/remove them from the Courier
table. We don’t want to truncate the table with each run.
We want to introduce a default courier field which will be in the Account TikTok
. The field will be an enum dropdown menu where the user can select the desired default courier. The field should not be required. Even if there is a selected default courier, we should first check if we have mapping from the courier on order with a record in table Courier
and pick this with priority. We should only pick the default courier if there is no mapping for the selected courier. We should not be able to send a shipping update and store an error in Order Errors
with Type
> Shipping if we don’t have mapped courier and if we don’t have default courier set.
API Call: GET /logistics/202309/delivery_options/{delivery_option_id}/shipping_providers
We need to pass the shop_cipher
as query property which was obtained with the Get Authorised Shops call found here TikTok - Authentication & Database structure
The delivery_option_id
parameter value will be what we have received from the above call and stored in TikTok Delivery Options
> Delivery Option ID
Example Request:
https://open-api.tiktokglobalshop.com/logistics/202309/delivery_options/6955034615128000261/shipping_providers?app_key=123abc&sign=5361235029d141222525e303d742f9e38aea052d10896d3197ab9d6233730b8c×tamp=1625484268&shop_cipher=ROW_RHkDDABBAAB8tKAVoAqsMTjsQZFLyNfY
Example Response:
{
"code": 0,
"data": {
"shipping_providers": [
{
"id": "7117858858072016686",
"name": "USPS"
}
]
},
"message": "Success",
"request_id": "202203070749000101890810281E8C70B7"
}
Ship Order
We want to use the new shipment model through the Order Shipment
table. We want all triggers & validatios to be as per our abstraction
Order management general requirements
<v1.3> With this call we are able to do partial shipment on orders, we could even ship single quantity of multi-quantity order. </v1.3>
When we send shipping request and If chosen courier is deleted from TikTok list, and we try to ship with this courier, we want to store an error in Order Errors
with Type
= Shipping (suggested error message: The courier you want to ship with is not part of TikTok couriers anymore.) and we will not send shipping request for this order. If there are no preselected carriers into the table TikTok couriers, we also want to store an error stating there is no courier selected.
We want to introduce Courier mapping, we already have a slave table called TikTok Couriers Mapping
for this use.
**The mapping will works based on:
If Order Shipment
> Carrier
match Courier
> Name
we send the selected courier from TikTok Courier Mapping
> TikTok Courier
If there is no match or no value in the mapping table we need to go into a second case which is to check directly in TikTok Couriers
table for the chosen courier. The check here is done against the Shipping Provider Name
column and if we find a match, we send the respective Shipping Provider ID
If there is no match on both of the above cases and we try to send a courier which is not part of the TikTok list, we want to store an error in Order Error
table with Type
= Shipment which states that the selected courier is not part of TikTok’s courier list.
<v1.3>
API Call: POST /fulfillment/202309/orders/{order_id}/packages
We should pick the order_id from Orders
> Marketplace Order ID
. The shipping provider id will be taken based on the mapping logic explained above.
We need to pass the shop_cipher
as query property which was obtained with the Get Authorised Shops call found here TikTok - Authentication & Database structure
Example Call:
{
"order_line_item_ids": [
"576719323145669659",
"576720553421999387"
],
"shipping_provider_id": "6599541761693270018",
"tracking_number": "H00KDA0040709141"
}
Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes |
---|---|---|---|---|
order_line_item_ids |
Yes | Order Item Line > Marketplace Order Item ID |
||
shipping_provider_id |
Yes | TikTok Courier > Shipping Provider ID |
Will be taken from the TikTok Carriers table; - The table will have 2 fields - TikTok Shipping Provider name & TikTok shipping Provider ID. |
We would want to map the shipping provider name but to send the shipping provider id to TikTok.
|
| tracking_number
| | Yes | Order Shipment
> Tracking Number
| |
Example response:
{
"code": 0,
"data": {
"order_id": "576719323145473051",
"order_line_item_ids": [
"576719323145669659"
],
"package_id": "1153248654705789979",
"warning": {
"message": "The tracking number you entered matches multiple logistics providers. Ensure you select the correct logistics provider."
}
},
"message": "Success",
"request_id": "202501231255414BC57038C018AD323E5E"
}
We don’t want to map anything from the success response. We also want to ignore the warning
object in this case. </v1.3>
<v1.2> Example error response :
{
"code": 21008099,
"data": null,
"message": "Package has been shipped. Please not ship the package again.",
"request_id": "20250123132004A3CFD57654E368327149"
}
Incase we receive any error in the response, we will have a code
different than 0. In this case we want to store the error message
in the Order Errors
table with Type
= Shipping. </v1.2>
</v1.1>