Tracking API
The v2.2 API is not backward compatible. We will keep the v1 API online.
When the v1 API is to be decommissioned in the future, we will notify you in advance by service chat group, email, and SMS. A live chat service specialist is also available (at the bottom right of the page) if you need any help.
About
17TRACK API is a standard logistics query interface. Through the API, you can query the logistics information of 2,100 carriers supported by 17TRACK. The API is based on HTTP protocol and is compatible with various development languages. Through the Webhook mechanism, the API realizes data transfer (register and push) and automatically tracks the logistics information for the entire shipping process. For supported carriers, please see https://www.17track.net/zh-cn/carriers.
Quick Guide
- Please make sure you have registered an API account here: https://api.17track.net.
- There will be 100 free tracking quota each month.
Step 1. Create a Webhook
- Create your own webhook endpoint or get one from webhook.site for you to test on.
- Save the webhook URL in the API dashboard settings page.
- For details about creating a webhook, settings and test, see the webhook section.
Step 2. Register a Tracking Number
- Get yourself a tracking number.
- Write a script to call the API and register the number, or use test tools like postman、apifox、apipost.
- All endpoints only accept requests with a single unique API Key.
- Take bash for example, set the key as the value of 17token inside of the request header,and pass the tracking number via number parameter (A maximum of 40 tracking numbers can be passed at a single time).
curl -X POST \ --header '17token:YourKey' \ --header 'Content-Type:application/json' \ --data '[ { "number": "RR123456789CN" }, { "number: "21213123123230" } ]' \ https://api.17track.net/track/v2.2/register
- If you receive a message like below, with code being 0, and some data in the accepted field, then the registration is successful.
{ "code": 0, "data": { "accepted": [ { "origin": 1, "number": "RR123456789CN", "carrier": 3011 } ], "rejected": [ { "number": "21213123123230", "error": { "code": -18019903, "message": "Carrier cannot be detected." } } ] } }
Step 3. Listen to Your Webhook for Tracking Updates
- The tracking results will be returned within seconds after the tracking number is registered (sometime it may go over 5 minutes due to internat or carrier issue).
- If you receive something like the below, it means the push process is all green.
{ "event": "TRACKING_UPDATED", "data": { "accepted": [ { "number": "RR123456789CN", "carrier": 3011, ... ... }, ... ... // Refer to the <TRACKING_UPDATED> for full details. ] } }
Get Security Key
Log in to the dashboard and go to Settings to get a key.
Change Security Key
Click on the "Change Key" button on Settings. The new key will take effect within 5 minutes. The old one will expire once the new key takes effect.
Notes
Important Things to Know
- It is not recommended to use JavaScript on webend for data security reasons.
- The interface frequency limit is 3req/s, a 429 error code will be returned when exceeding the limit.
- All time in the response messages is in UTC format.
- All endpoints are compatible with new features in the future.
- All response data will show "Null" when there is no valid information.
- How Automatical tracking works:
- The tracking results will be returned within seconds after the tracking number is registered (sometime it may go over 5 minutes due to internat or carrier issue).
- Subsequent trackings will be made every 6~12 hours based on the shipping status checked last time. For delivered and exception packages, the tracking will be made every 24 hours.
- Starting from the Tracking Time, the system will stop the tracking if there is no event update from the carrier for 30 consecutive days since then.
- The system will stop the tracking if the package is delivered and stays that way for 15 consecutive days.
- The stopped tracking can be re-activate for 1 time.
- The stopped tracking will remain in your account for 90 days before it gets deleted by the system.
Tracking Quota
- The quota is only calculated when a tracking number is registered successfully.
- Each quota is associated with one tracking number. It will not be calculated if you track the same number for multiple times.
- The identity of each tracking number is determined by the tracking number itself and the carrier code it assigned with.
- In some cases, the tracking numbers were once deleted by you or by the system due to the expiration rule. If you want to re-register them to keep tracking again, the quota will be deducted.
Basic Concept and Definition
Carrier Code
You can find the code of each carrier under the "key" field in the data listed below. Use it as the value of the carrier parameter to specify a carrier.
- The carrier code list in JSON See here.
- The carrier code list in CSV See here.
- We keep adding new carriers to our support. Please visit these data regularly to stay up-to-date.
Additional parameters for tracking
- Additional params are required to track the shipments of some carriers, please refer to the following.
Carrier Name | Carrier Code | Param | Sample | Require |
---|---|---|---|---|
Bpost | 2061 | PostalCode | 1000 | FALSE |
DHL Paket | 7041 | PostalCode | 1000 AA | FALSE |
PostNL | 14041 | DestCountry | FR | TRUE |
PostNL | 14041 | PostalCode | 1000 AA | FALSE |
FedEx | 100003 | ShipDate | 2024/1/1 | FALSE |
GLS | 100005 | PostalCode | TRUE | |
GLS (IT) | 100024 | PostalCode | FALSE | |
BRT Bartolini(DPD) | 100026 | PostalCode | 1000 AA | FALSE |
Colis Prive(Colis Privé) | 100027 | PostalCode | 12345 | FALSE |
J&T Express (ID) | 100074 | PhoneNumber | 8888 | TRUE |
Caribou | 100078 | PostalCode | 1000 | FALSE |
Commonline | 100155 | PostalCode | 1000 | FALSE |
XDP EXPRESS | 100167 | PostalCode | LS27 0BN | TRUE |
GLS Spain (National) | 100189 | PostalCode | 123456 | TRUE |
GLS (Croatia) | 100207 | PostalCode | TRUE | |
J&T Express (TH) | 100271 | PhoneNumber | 8888 | TRUE |
GLS (HU) | 100280 | PostalCode | TRUE | |
GLS (CZ) | 100281 | PostalCode | TRUE | |
GLS (SK) | 100282 | PostalCode | TRUE | |
GLS (SI) | 100283 | PostalCode | TRUE | |
GLS (RO) | 100284 | PostalCode | TRUE | |
Mondial Relay | 100304 | PostalCode | 123456 | TRUE |
GLS (PT) | 100316 | PostalCode | TRUE | |
DPD (BE) | 100321 | PostalCode | 1000 AA | FALSE |
GEODIS | 100356 | PostalCode | 1000 AA | FALSE |
Paack | 100364 | PostalCode | 12345 | TRUE |
GLS (NL) | 100384 | PostalCode | 12345 | TRUE |
J&T Express (MX) | 100388 | PhoneNumber | 8888 | TRUE |
Pall-Ex (UK) | 100394 | PostalCode | CO14 8LF | TRUE |
GEL Express Logistik | 100396 | PostalCode | 1000 AA | FALSE |
Gebrüder Weiss (GW) | 100431 | Postal Code/City/Country/shipper/consignee. | TRUE | |
Nacex | 100436 | PostalCode | 1234 | TRUE |
Seur | 100438 | PhoneNumber | 8888 | TRUE |
Seur | 100438 | PostalCode | 28001 | TRUE |
J&T Express (VN) | 100456 | PhoneNumber | 8888 | TRUE |
Cycloon (Fietskoeriers) | 100466 | PostalCode | 1000 AA | TRUE |
DPD (CZ) | 100483 | PostalCode | 1000 AA | FALSE |
DX | 100484 | PostalCode | 12345 | TRUE |
Ryder | 100522 | PostalCode | 88888 | TRUE |
Tuffnells | 100524 | PostalCode | S27 1BZ | TRUE |
Postmedia Parcel Services (BNI Parcel Tracking) | 100552 | PostalCode | H4E 5R4 | TRUE |
DPD (AT) | 100556 | PostalCode | 1000 AA | FALSE |
Walkers Transport | 100580 | PostalCode | LS27 0BN | TRUE |
DPD (HU) | 100584 | PostalCode | 1000 AA | FALSE |
InPost (ES) | 100594 | PostalCode | 51900 | TRUE |
InPost (PT) | 100598 | PostalCode | 51900 | TRUE |
J&T Express (EG) | 100619 | PhoneNumber | 8888 | TRUE |
Allied Express Transport | 100623 | PostalCode | 1000 | TRUE |
GLS Portugal (National) | 100646 | PostalCode | 1000-205 | TRUE |
A TU HORA EXPRESS | 100688 | PostalCode | 1000 | FALSE |
J&T Express (BR) | 100797 | PostalCode | CPF/CNPJ | TRUE |
DPD (HR) | 100807 | PostalCode | 1000 AA | FALSE |
DPD (EE) | 100808 | PostalCode | 1000 AA | FALSE |
DPD (LV) | 100809 | PostalCode | 1000 AA | FALSE |
DPD (LT) | 100810 | PostalCode | 1000 AA | FALSE |
DPD (NL) | 100811 | PostalCode | 1000 AA | FALSE |
DPD (SK) | 100812 | PostalCode | 1000 AA | FALSE |
DPD (SI) | 100813 | PostalCode | 1000 AA | FALSE |
DPD (CH) | 100815 | PostalCode | 1000 AA | FALSE |
DHL Supply Chain APAC | 100842 | DestCountry | ID | TRUE |
The United Pallet Network | 100862 | PostalCode | LS27 0BN | TRUE |
Furdeco | 100881 | PostalCode | LS27 0BN | TRUE |
Palletways | 100900 | PostalCode | 1000 AA | FALSE |
Instabox | 100932 | PostalCode | 51900 | TRUE |
France Express | 100936 | PostalCode | 1000 AA | FALSE |
Transaher | 100959 | PostalCode | 12345 | FALSE |
BJS Home Delivery | 101003 | PhoneNumber | 8888888888 | TRUE |
Palletforce | 101010 | PostalCode | S27 1BZ | TRUE |
FleetOptics | 101035 | PostalCode | 1000 | TRUE |
Hofmann | 101038 | PostalCode | 10000 | TRUE |
Emons | 101039 | PostalCode | 10000 | TRUE |
Sislógica | 101040 | PostalCode | 1000000 | TRUE |
APC Overnight | 101065 | PostalCode | 1000 AA | TRUE |
Arrow XL | 101076 | PostalCode | 1000 AA | FALSE |
UC Express | 190415 | PhoneNumber | 8888 | TRUE |
SF Express(CN) | 190766 | PhoneNumber | 8888 | TRUE |
KYE (CN) | 190845 | PhoneNumber | 8888 | TRUE |
Country and Region Code
- The country and region code is in ISO 3166-1 format.
Main Status of the Shipping Process
- There are 9 main satatus, each representing a unique logistics process the package is in. The status are a enum set.
- Milestones have the same meaning as main/sub status. However, it may not always show depending on the carrier's data.
- In the v2.2 API, a status is given as a string under the lastest_status.status property. While in the v1 API, it is given as a number code under the e property.
Main Status |
Description |
---|---|
NotFound | The inquiry is made successfully but nothing can be found for this tracking number. See sub-statues for more details. |
InfoReceived | The carrier has received the order info and is about to pick up the package from the sender. |
InTransit | The package is in transit. See sub-status for more details |
Expired | The package has been in transit for a long time and not yet delivered. |
AvailableForPickup | The package has arrived at the pick up point of the destination. |
OutForDelivery | The package is out for delivery |
DeliveryFailure | The package was attempted to be delivered but not successfully failed. Please refer to the sub-status for the reason. The reasons may be: the recipient is not at home at the time of delivery, the delivery is delayed and is now rescheduled for another attempt, the recipient requests to postpone the delivery, the address is unknown and cannot be delivered, no delivery service is available due to remote areas, etc. |
Delivered | The package is delivered and signed by the recipient. |
Exception | The package may be returned, please refer to the sub-status for the reason. Reasons may be: recipient's address is wrong or unknown, recipient refuses to accept, parcel is unclaimed beyond the retention period, etc. The package may be detained by customs, common reasons for detention are: containing sensitive prohibited, restricted import and export items, unpaid taxes, etc. Parcels may suffer damage, loss, delayed delivery and other special circumstances in transit. |
Sub-status of the Shipping Status
- There are 30 sub status, each representing a specific cause or explanation to the main status. The status are a enum set.
- They are the subdivision of the main status and gives more details about what process the package is in.
- A sub status is given as a string under the latest_status.sub_status property.
Main Status | Sub-Status | Description |
---|---|---|
NotFound | NotFound_Other | The carrier didn't return any message. |
NotFound_InvalidCode | The tracking number is invalid. | |
InfoReceived | InfoReceived | No specific breakdown of meaning, same with the main status. |
InTransit | InTransit_PickedUp | The carrier has collected the package from the sender. |
InTransit_Other | Other circumstances beyond the currently known sub-statuses. | |
InTransit_Departure | Package has left the originating country/region's port. | |
InTransit_Arrival | Package has arrived at the destination country/region's port. | |
InTransit_CustomsProcessing | Your shipment is under the customs clearance process. | |
InTransit_CustomsReleased | Import/Export customs clearance is completed. | |
InTransit_CustomsRequiringInformation | Related information is required for clearance. | |
Expired | Expired_Other | No specific breakdown of meaning, same with the main status. |
AvailableForPickup | AvailableForPickup_Other | No specific breakdown of meaning, same with the main status. |
OutForDelivery | OutForDelivery_Other | No specific breakdown of meaning, same with the main status. |
DeliveryFailure | DeliveryFailure_Other | Other circumstances beyond the currently known sub-statuses. |
DeliveryFailure_NoBody | Unable to contact the recipient temporarily during the delivery process, resulting in delivery failure. | |
DeliveryFailure_Security | Package encountered security, customs clearance, or fee issues during delivery, resulting in delivery failure. | |
DeliveryFailure_Rejected | Recipient refused to accept the package for certain reasons, resulting in delivery failure. | |
DeliveryFailure_InvalidAddress | Delivery failure due to an incorrect recipient address. | |
Delivered | Delivered_Other | No specific breakdown of meaning, same with the main status. |
Exception | Exception_Other | Other circumstances beyond the currently known sub-statuses. |
Exception_Returning | Package is being returned to the sender. | |
Exception_Returned | Sender has successfully received the returned package. | |
Exception_NoBody | Cannot find the receipient due to the abnormal recipient information discovered before delivery | |
Exception_Security | Abnormalities found before delivery, including security, customs clearance, or fee issues. | |
Exception_Damage | The pacakge was found damaged during the transportation process. | |
Exception_Rejected | Recipient refused to accept the package before delivery. | |
Exception_Delayed | Possible delay beyond the original scheduled transit time due to various circumstances. | |
Exception_Lost | Package lost due to various circumstances. | |
Exception_Destroyed | Package unable to be delivered for various reasons and subsequently destroyed. | |
Exception_Cancel | Shipment order was cancelled due to various circumstances. |
Translating Language Codes
The code used to translate logistic events, please refer to the Register tracking number and Change Registration Info interface descriptions.
Language |
Code |
---|---|
English | en |
Japanese | ja |
French | fr |
Danish | da |
Thai | th |
German | de |
Spanish | es |
Simplified Chinese | zh-hans |
How to get the pickup time
- Iterate through tracking.providers[].events[].
- Priority check: If sub_status == "InTransit_PickedUp", then the content of time_raw represents the pickup time.
- If there is no matching value, use the time of the first event with sub_status == "InTransit_xxx" as the pickup time.
- If neither of the above conditions retrieves a value for time_raw, it indicates incomplete event descriptions from the carrier and cannot be provided.
How to get delivery time
- Iterate through tracking.providers[].events[]. If sub_status == "Delivered_Other", then the content of time_raw represents the delivery time.
API Usage
About General Request
- Use http POST method to submit requests for all endpoints.
- All requests and responses are in UTF-8 encoded JSON format.
- Frequently used parameters:
- Tracking Number (number): must be a combination of 5 to 50 consecutive letters, numbers and/or hyphen.
- Carrier Code (carrier): must be on the List of Carrier Code.
- For other parameters, please see the description of for endpoint.
- Request URL:https://api.17track.net/track/v2.2
- Request Head(Required)
- 17token: Security Key.
- Content-Type: application/json.
- Request Body(Required)
- Serialized JSON content. For Google Apps Script, use payload as the request body.
Example Request
curl -X POST \
--header '17token:SecurityKey' \
--header 'Content-Type:application/json' \
--data '[{"number":"RR123456789CN", "carrier":3011}]' \
https://api.17track.net/track/v2.2/interfaceName
Response
Example Response 1. This syntax will show when illegal parameters are passed in.
{
"code": 0,
"data": {
"errors": [
{
"code": -18010013,
"message": "Submitted data is invalid."
}
]
}
}
The response results are in a uniform data encapsulation format, as described below:
Property | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-errors | |
--code | The HTTP Status code and error code. |
--message | Error description. |
Example Response 2
{
"code": 0,
"data": {
"accepted": [],
"rejected": []
}
}
The response results are in a uniform data encapsulation format, as described below:
Property | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
- accepted | The response of the successfully processed part of the request. |
- rejected | The response of the unsuccessfully processed part of the request. |
List of HTTP Status Code
Code | Description |
---|---|
200 | The request is processed successfully. You can see the result in the returned data. |
401 | Unauthorized request, incorrect security key, IP not in the whitelist, or account disabled. |
404 | Incorrect request URL. |
429 | Request frequency exceeds governing threshold. |
500 | Server error. |
503 | Service temporarily suspended. |
List of Error Codes
An error code is a more specific status based on the response status code:
Code | Description |
---|---|
0 | Success |
-18010001 | Your IP is not in the whitelist. You can set it in the dashboard. |
-18010002 | Invalid security key. |
-18010003 | Internal service error. Please try again later. |
-18010004 | The account is disabled. |
-18010005 | Unauthorized access. |
-18010010 | Please provide the data {0}. |
-18010011 | The value of data {0} is invalid. |
-18010012 | The format of the data {0} is invalid. |
-18010013 | Invalid submitted data. |
-18010014 | Tracking numbers exceed 40 limit. |
-18010015 | The value {0} of the field {1} is invalid. |
-18010016 | Last-mile carrier can only be set for postal services. |
-18010018 | The '{1}' field is required for this tracking. Please provide Alpha-2 country code and postal code. Example: '{0}'. |
-18010019 | The '{1}' field is required for this tracking. Please provide postal code. Example: '{0}'. |
-18010020 | The '{1}' field is required for this tracking. Please provide phone number. Example: '{0}'. |
-18010022 | Additional information is needed to continue tracking your package. Example: '2024-01-01'. |
-18010201 | Webhook URL is required. |
-18010202 | Incorrect URL format of 'Webhook'. |
-18010203 | WebHook test failed, Http status code: {0}. |
-18010204 | Webhook URL not set, can't push data. |
-18010205 | Incorrect IP format. |
-18010206 | Push failed. |
-18019901 | Tracking number {0} is already registered. |
-18019902 | Tracking number {0} is not registered yet. Please register first. |
-18019903 | The carrier can not be detected, please visit https://res.17track.net/asset/carrier/info/apicarrier.all.json for the carrier code and send in as the parameter. |
-18019904 | Only stopped numbers can be re-tracked. |
-18019905 | Each tracking number can only be re-tracked once. |
-18019906 | Only numbers being tracked can be stopped. |
-18019907 | Tracking amount exceeds your daily limit. |
-18019908 | Your quotas have ran out. |
-18019909 | No tracking info at the moment. |
-18019910 | Carrier Code {0} is incorrect. |
-18019911 | The tracking number of this carrier can not be registered at the moment. |
-18019801 | The tracking number is registered with multiple carriers. Please specify which tracking number you want to change the carrier code for by specifying the carrier_old parameter. |
-18019802 | The parameter carrier_new {0} is incorrect. |
-18019803 | The Carrier Code to be changed can not be the same of the current one. |
-18019804 | The Carrier Code to be changed must be specified to carrier_new or final_carrier_new. |
-18019805 | The tracking number {1} for the specified carrier {0} is not registered, or the existing carrier parameter carrier_old is incorrect. |
-18019806 | Carrier can not be changed for stopped numbers. Please retrack the number before changing the carrier. |
-18019807 | The times for changing carrier exceed limit. |
-18019808 | The tracking result has not been returned after the latest registration or modification. Please wait for the tracking result to be returned before changing it. |
-18019809 | The registration information of the carrier with tracking number {0} already exists and cannot be changed to a duplicate registration information. |
-18019810 | Data that meet the update condition are not unique. |
-18019811 | The data need to be changed is not valid. |
-18019818 | The carrier is not supported in the real-time tracking interface. |
-18019817 | System error; the charge for this request was not processed. |
-18019816 | The carrier interface encountered an error, and no tracking results were retrieved. |
-18019815 | The carrier interface response timed out. |
-18019912 | Unauthorized account access to the real-time tracking interface. |
Register tracking number - POST https://api.17track.net/track/v2.2/register
- The endpoint receives 40 numbers at most at a single time.
- The tracking results will be returned within seconds after the tracking number is registered (sometime it may go over 5 minutes due to internat or carrier issue).
- About 400,000 tracking numbers can be registered in an hour.
- Pass in the translation language code to be translated after the logistics event has changed and is not empty.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]' \
https://api.17track.net/track/v2.2/register
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/register",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>"[
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/register"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/register")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/register',
headers: {
'content-type': 'application/json',
'17token': 'your secret key',
},
data: '[
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/register"
payload = [
{
"number": "RR123456789CN",
"lang": "",
"email":"",
"param": "",
"order_no": "202340984938",
"order_time": "2023/1/1",
"carrier": 3011,
"final_carrier": 21051,
"auto_detection": true,
"tag": "MyOrderId",
"remark": "My Remarks"
},
{
"number": "1234",
"tag": "My-Order-ID"
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Request Parameter:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number you want to register. It must conform to the tracking number format. |
lang | No | String | Used to translate logistics events, as detailed below. 1. specify the translation language code. 2. translation needs to consume 1 additional single volume, i.e.: tracking + translation actually deducts 2 single. 3. to translate and deduct the fee when the result is tracked for the first time after successfully registering the single number, and subsequent updates will automatically translate and no longer deduct the fee. |
No | String | User email, no more than 250 characters. After the email notifications feature is activated, we'll notify users via this email when package status changes. | |
param | No | String | Additional parameter like postcode, order date, etc., required by some carriers along with the tracking number. |
order_no | No | String | Must be a combination of 5 to 50 characters including letters, numbers, or dashes. |
order_time | No | DateTime | order placed time, use it to calculate the Scanned performance, e.g: 2023/1/1. |
carrier | No | Int. | 1. Pass in the Carrier Code if you want to specify a carrier for the tracking number. 2. The tracking numbers of most UPU and commercial carriers can be auto-identified by our system. If you do not pass in or pass in the wrong carrier code, the system will match the most possible carrier and return its Carrier Code. 3. If you receive a -18019903 error when you do not pass in a code, it means the system can not find a matched carrier at all. You will need to register the number again with a Carrier Code. |
final_carrier | No | Int. | Carrier Code of the last-mile carrier. (Only for UPU numbers) |
auto_detection | No | Boolean | Turn on and off the carrier auto detection, true by default. This does not always guarantee an accurate result if at all. The parameter will be ignored if a carrier parameter is passed in. |
tag | No | String | A tag you can note anything down with no more than 100 characters. You can use it to add additional info, categorize your numbers, etc. |
remark | No | String | No more than 1,000 characters, you can use it to describe the current package status. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"origin": 1,
"number": "RR123456789CN",
"carrier": 3011,
"email": null,
"tag": "MyOrderID",
"lang": null,
}
],
"rejected": [
{
"number": "1234",
"tag": "My-Order-Id",
"error": {
"code": -18010012,
"message": "The format of '1234' is invalid."
}
}
]
}
}
Response Explanation:
Property | Type |
Description |
---|---|---|
code | Int. | The HTTP Status code and error code. |
data | Object | The response data. |
-accepted | Array | Tracking number registered and its carrier code will be returned. If the carrier code sent in was invalid or belongs to another carrier, the system will correct it and returned the right one. |
--number | String | The tracking number registered. |
--tag | String | Custom tag. See tracking number registration for more info. |
--carrier | Int. | The Carrier Code. |
String | ||
--lang | String | Translating Language Code |
--origin | Int. | This shows a number code representing how the carrier code is provided: If it shows 1: A confidant result given by the system including auto-detection or the correction by the system based on the code passed in. If it shows 2. The carrier code is passed in which is also found correct by the system. If it shows 3. The carrier code is not passed in, and a guess was provided by the system, may not always be correct. |
-rejected | Array | This shows the tracking numbers failed to be registered, with an error code and a message explaning the cause. |
--number | String | The tracking number must conform to the tracking number format. |
--error | Object | |
---code | Int. | Error code. |
--message | String | Error description. |
Change Carrier - POST https://api.17track.net/track/v2.2/changecarrier
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- You can reassign a carrier for a tracking number by passing in the new carrier code and the old carrier code that needs to be replaced.
- You can change the carrier ofr a tracking for 5 times at most.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]' \
https://api.17track.net/track/v2.2/changecarrier
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/changecarrier",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/changecarrier"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/changecarrier")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/changecarrier',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/changecarrier"
payload = [
{
"number": "RR123456789CN",
"carrier_old": 3013,
"carrier_new": 3011
},
{
"number": "21213123123230",
"carrier_old": 3011,
"carrier_new": 21051,
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number you want to change the carrier for. It must conform to the Tracking Number Format. |
carrier_old | No | Int. | The old Carrier Code that needs to be replaced. If you have assigned multiple carriers to a single tracking number, it helps specify which one of them you want to change. You can ignore this parameter if only one carrier is assiged to the tracking number. |
carrier_new | Yes | Int. | The new Carrier Code that needs to be changed into. |
final_carrier_old | No | Int. | The old last-mile Carrier Code that needs to be replaced. Only available for UPU carriers. |
final_carrier_new | Yes | Int. | The new last-mile Carrier Code that needs to be changed into. Only available for UPU carriers. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"carrier": 3011
}
],
"rejected": [
{
"number": "21213123123230",
"error": {
"code": -18019809,
"message": "The registration information of the carrier with tracking number 'Usa' already exists and cannot be changed to a duplicate registration information."
}
}
]
}
}
Response Explanation:
Item | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | This shows the tracking number whose carrier has been changed successfully. The new carrier code will be returned as well. |
-rejected | This shows the tracking numbers failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Change Registration Info - POST https://api.17track.net/track/v2.2/changeinfo
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- Use this endpoint to change the attached info of a tracking number.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]' \
https://api.17track.net/track/v2.2/changeinfo
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/changeinfo",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/changeinfo"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/changeinfo")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/changeinfo',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/changeinfo"
payload = [
{
"number": "RR123456789CN",
"carrier": 3011,
"items": {
"lang": "en",
"param": "8888",
"tag": "This is my order id."
}
},
{
"number": "21213123123230",
"carrier": 11031,
"items": {
"tag":"This is my order id."
}
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number must conform to the tracking number format. |
carrier | No | Int. | The Carrier Code of the tracking number. |
items | Yes | Object | The set of data that needs to be changed, only "tag" can be changed for now, other parameter will be ignored. |
--tag | No | String | Custom tag. See tracking number registration for more info. |
--param | No | String | Additional parameters |
--lang | No | String | Specify the translation language code to be automatically translated at the next logistics event change. |
Example Response
{ "code": 0, "data": { "accepted": [ { "number": "RR123456789CN", "carrier": 3011 } ], "rejected": [ { "number": "21213123123230", "error": { "code": -18019902, "message": "The tracking number '21213123123230' does not register, please register first." } } ] } }
Response Explanation:
Item | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | The data that has been received and processed successfully. The latest Carrier Code will be returned. |
-rejected | The data failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Stop Tracking - POST https://api.17track.net/track/v2.2/stoptrack
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- Use this to stop the tracking of a tracking number.
- This operation is the opposite of retrack.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]' \
https://api.17track.net/track/v2.2/stoptrack
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/stoptrack",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/stoptrack"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/stoptrack")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/stoptrack',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/stoptrack"
payload = [
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number must conform to the tracking number format. |
carrier | No | Int. | Carrier Code. If not passed in and if the tracking number can be matched to multiple carriers, it will be processed for multiple times for each carrier matched. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"carrier": 3011
}
],
"rejected": [
{
"number": "21213123123230",
"error": {
"code": -18019902,
"message": "The tracking number '21213123123230' does not register, please register first."
}
}
]
}
}
Response Explanation:
Item | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | This shows the data that has been received and processed successfully. |
-rejected | This shows the tracking numbers failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Retrack a stopped tracking number - POST https://api.17track.net/track/v2.2/retrack
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- Restart the automatic tracking for a tracking number that has been stopped.
- This operation is the opposite of the stoptrack endpoint.
- Every tracking number can only be restarted for once.
Example Request
curl -X POST \
--header '17token:SecurityKey' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]' \
https://api.17track.net/track/v2.2/retrack
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/retrack",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/retrack"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/retrack")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/retrack',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/retrack"
payload = [
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number must conform to the tracking number format. |
carrier | No | Int. | Carrier Code. If not passed in and if the tracking number can be matched to multiple carriers, it will be processed for multiple times for each carrier matched. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"carrier": 3011
}
],
"rejected": [
{
"number": "21213123123230",
"error": {
"code": -18019904,
"message": "Retrack is not allowed. You can only retrack stopped number."
}
}
]
}
}
Response Explanation:
Item |
Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | This shows the data that has been received and processed successfully. |
-rejected | This shows the tracking numbers failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Delete a tracking number - POST https://api.17track.net/track/v2.2/deletetrack
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- The delete action can not be undone.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]' \
https://api.17track.net/track/v2.2/deletetrack
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/deletetrack",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/deletetrack"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/deletetrack")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/deletetrack',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/deletetrack"
payload = [
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | Tracking number must conform to the tracking number format. |
carrier | No | Int. | Carrier Code. If not passed in and if the tracking number can be matched to multiple carriers, it will be processed for multiple times for each carrier matched. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"carrier": 3011
}
],
"rejected": [
{
"number": "21213123123230",
"error": {
"code": -18019902,
"message": "The tracking number '21213123123230' does not register, please register first."
}
}
]
}
}
Response Explanation:
Item | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | This shows the data that has been received and processed successfully. |
-rejected | This shows the tracking numbers failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Get the quota info - POST https://api.17track.net/track/v2.2/getquota
- You can use this endpoint to see the status of your quota. No parameter is needed.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
https://api.17track.net/track/v2.2/getquota
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/getquota",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/getquota"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/getquota")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/getquota',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/getquota"
payload = []
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Example Response
{ "code": 0, "data": { "quota_total": 1100, "quota_used": 2, "quota_remain": 1098, "today_used": 0, "max_track_daily": 10000000, "free_email_quota": 300, "free_email_quotaused": 0 } }
Response Explanation:
Item | Type |
Description |
---|---|---|
code | Int. | The HTTP Status code and error code. |
data | Object | The response data. |
-quota_total | Int. | Current quota in total. |
-quota_used | Int. | Current quota used. |
-quota_remain | Int. | How many usable quota left. |
-max_track_daily | Int. | The daily quota limit set by you, with 0 meaning no limit. |
-free_email_quota | Int. | Free email quota. |
-free_email_quotaused | Int. | Email quota consumed. |
Search Tracking Info by Condition - POST https://api.17track.net/track/v2.2/gettracklist
- Use this endpoint to search tracking info and get returned data in 1 page with 40 messages at most.
- The parameters for this endpoint are mainly used as the filter condition for the search.
- This endpoint does not initiate any tracking action. It retrive info from the tracking data of the registered number.
Excample Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '{
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin":"Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc",
}' \
https://api.17track.net/track/v2.2/gettracklist
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/gettracklist",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>'{
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin":"Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc"
}',
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/gettracklist"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("{
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin":"Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc"
}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "{
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin":"Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc"
}";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/gettracklist")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/gettracklist',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: JSON.stringify({
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin": "Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc"
});
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/gettracklist"
payload = {
"number": "RR123456789CN,RR111111111CN",
"carrier": 3011,
"data_origin": "Api",
"register_time_from": "2019-01-01",
"register_time_to": "2019-02-01",
"track_time_from": "2019-01-01",
"track_time_to": "2019-12-01",
"push_time_from": "2019-01-01",
"push_time_to": "2019-12-01",
"push_status": "Success",
"stop_track_time_from": "2019-01-01",
"stop_track_time_to": "2019-12-01",
"package_status": "NotFound",
"tracking_status": "Tracking",
"page_no": 1,
"order_by": "PushTimeAsc"
}
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | No | String | Tracking Number, pass in more than 1 number will ger more precise filters, 200 numbers at most(separated by comma). Each number must conform to the tracking number format. |
carrier | No | Int. | See Carrier Code. |
data_origin | No | Enum. | Upload Source. "Api" "Manual" "Import" |
package_status | No | Int. | See Package status. |
register_time_from | No | DateTime | The range of time of registration starts at. |
register_time_to | No | DateTime | The range of time of registration ends at. |
tracking_status | No | Enum. | "Tracking" "Stopped" |
track_time_from | No | DateTime | The range of time of tracking starts at. |
track_time_to | No | DateTime | The range of time of tracking ends at. |
push_time_from | No | DateTime | The range of time of push starts at. |
push_time_to | No | DateTime | The range of time of push ends at. |
push_status | No | Enum. | "NotPushed" "Success" "Failure" |
push_status_code | No | The HTTP Status code. | |
stop_track_time_from | No | DateTime | The range of time of stopped tracking starts at. |
stop_track_time_to | No | DateTime | The range of time of stopped tracking Ends at. |
page_no | No | Int. | Page Number. |
order_by | No | Enum. | Show in the oreder of: "RegisterTimeAsc" "RegisterTimeDesc" "PushTimeAsc" "PushTimeDesc" "TrackTimeAsc" "TrackTimeDesc" |
Example Request
{
"page": {
"data_total": 43,
"page_total": 2,
"page_no": 1,
"page_size": 40
},
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"param": null,
"param_type": "None",
"data_origin": "Api",
"carrier": 3011,
"shipping_country": "CN",
"final_carrier": 0,
"recipient_country": "RU",
"register_time": "2022-03-14T07:45:38Z",
"tracking_status": "Tracking",
"package_status": "Delivered",
"track_time": "2022-03-14T07:45:22Z",
"push_time": "2022-03-14T07:47:42Z",
"push_status": "Success",
"push_status_code":200,
"stop_track_time": null,
"stop_track_reason": null,
"is_retracked": false,
"carrier_change_count": 0,
"tag": null,
"email":"",
"order_no": "86574382938",
"order_time": "2022-04-25T22:22:47+05:00",
"lang":"",
"remark": "test",
"latest_event_time": "2023-08-05T10:00:21+05:00",
"latest_event_info": "FAISALABAD,Shipment has been Delivered. Delivery Date & Time Aug 5 2023 9:48AM and Received By: Shahzad",
"days_after_order ":2,
"days_after_last_update ":null,
"days_of_transit ":2,
"days_of_transit_done ":2,
"delievery_time": "2023-08-05T05:00:21Z",
"pickup_time": ""
}
]
}
}
Response Explanation:
Item | Type |
Description |
---|---|---|
page | Object | Page information. |
-data_total | Int. | Total data count. |
-page_total | Int. | Total page count. |
-page_no | Int. | Current page index (default 0) |
-page_size | Int. | Number of data per page (default 40, maximum 40) |
code | Int. | The HTTP Status code and error code. |
data | Object | The response data. |
-accepted | Object | This shows the data that has been received and processed successfully. |
--number | String | Tracking number. |
--param_type | Enum. | Additional tracking parameters types. "None" "PostalCode" "PhoneLast4Digits" "Alpha-2CountryCode&PostalCode" "OriginOffice" "Client" |
--param | String | Additional parameter like postcode, order date, etc., required by some carriers along with the tracking number. |
--data_origin | Enum. | Upload Source. "Api" "Manual" "Import" |
--carrier | Int. | Carrier code. |
--final_carrier | Int. | Carrier Code of the last-mile carrier. |
--package_status | String | Package status. |
--shipping_country | String | The country where the package is originated. |
--recipient_country | String | The country where the package is sent to. |
--register_time | String | The time when the tracking number is registered. |
--tracking_status | String | Tracking status: "Tracking" "Stopped" |
--track_time | String | The latest tracking time. |
--push_time | String | The latest push time. |
--push_status | String | Push status: "NotPushed" "Success" "Failure" |
--push_status_code | Int. | Code for push_status see [HTTP Status Code] and Error code. |
--stop_track_time | Int. | The time when the tracking stopped. |
--stop_track_reason | String | The reason why the tracking is stopped: "Expired":Stopped by system's expiration policy. "ByRequest":Stopped by a request. "InvalidCarrier":Stopped becuase the carrier is not valid. |
--is_retracked | Boolean | If the tracking number is re-tracked. |
--carrier_change_count | Int. | How many times the carrier of the tracking number is changed. 5 being the highest limit. |
--tag | String | Custom tag, see Tracking number registration. |
--order_no | String | Order Number |
--order_time | DateTime | Order Date |
String | ||
--lang | String | Translating Language Code |
--remark | String | Note |
--latest_event_time | DateTime | Latest Event Time |
--latest_event_info | String | Latest Event |
--days_after_order | Int. | Order Transit Time(in days) Calculation: 1. For delivered status, Order Transit Time(in days) = Delivery Date - First Event Date. 2. For non-delivered status, with tracking result, Order Transit Time(in days) = Current Date - First Event Date. 3. No tracking result, Order Transit Time(in days) = 0. |
--days_after_last_update | Int. | No Update Days: 1. For delivered, return to sender, and no result status, interval in days = 0. 2. For other cases, interval in days = Current Date - Last Event Date. |
--days_of_transit | Int. | Transit Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Transit Time(in days) = Delivery Date - Pickedup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and “InfoReceived”,Transit Time(in days) = Delivery Date - First Event Date. For non-delivered status , with tracking result: 1. With “InTransit_PickedUp”,Transit Time(in days) = Current Date - Pickup Date 2. WIthout “InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Current Date - First Event Date after "InfoReceived". 3. WIthout "InTransit_PickedUp",with "InfoReceived",and only one tracking event, Transit Time(in days) = 0. 4. Without both "InTransit_PickedUp" and "InfoReceived",Transit Time(in days) = Current Date - First Event Date. No tracking result: Transit Time(in days) = 0. |
--days_of_transit_done | Int. | Delivery Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Delivery Time(in days) = Delivery Date - Pickup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Delivery Time(in days) =Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and "InfoReceived",Delivery Time(in days) = Delivery Date - First Event Date. For non-delivered status: Delivery Time(in days) = 0. |
--delievery_time | DateTime | Delivery date |
--pickup_time | DateTime | Picked up date |
Get Tracking Details - POST https://api.17track.net/track/v2.2/gettrackinfo
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- The usage logic of this endpoint is the same as getracklist.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]' \
https://api.17track.net/track/v2.2/gettrackinfo
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/gettrackinfo",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/gettrackinfo"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/gettrackinfo")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/gettrackinfo',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/gettrackinfo"
payload = [
{
"number": "270434455123",
"carrier": 100003
},
{
"number": "21213123123230",
"carrier": 21051
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number must conform to the tracking number format. |
carrier | No | Int. | Carrier code. If not passed in and if the tracking number can be matched to multiple carriers, it will be processed for multiple times for each carrier matched. |
Example Response
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123465789CN",
"carrier": 100003,
"param": "232296506",
"tag": "myID",
"track_info": {
"shipping_info": {
"shipper_address": {
"country": "CN",
"state": "GD",
"city": "SHENZHEN",
"street": "HARTFORD CT DISTRIBUTION CENTER",
"postal_code": "518000",
"coordinates": {
"longitude": "114.085947",
"latitude": "22.547"
}
},
"recipient_address": {
"country": "AF",
"state": null,
"city": "KABUL",
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
}
},
"latest_status": {
"status": "InfoReceived",
"sub_status": "InfoReceived",
"sub_status_descr": null
},
"latest_event": {
"time_iso": "2022-03-02T20:43:24-06:00",
"time_utc": "2022-03-03T02:43:24Z",
"time_raw": {
"date": "2022-03-02",
"time": "20:43:24",
"timezone": "-06:00"
},
"description": "Shipment information sent to FedEx",
"description_translation": {
"lang": "en",
"description": "Shipment information sent to FedEx"
},
"location": "NJ",
"stage": "InfoReceived",
"sub_status": "InfoReceived",
"address": {
"country": "US",
"state": "NJ",
"city": "MARLTON",
"street": null,
"postal_code": "08053",
"coordinates": {
"longitude": null,
"latitude": null
}
}
},
"time_metrics": {
"days_after_order": 7,
"days_of_transit": 7,
"days_of_transit_done": 7,
"days_after_last_update": 57,
"estimated_delivery_date": {
"source":"Official",
"from": "2021-09-01T08:00:54-05:00",
"to": "2021-09-01T13:00:45-05:00"
}
},
"milestone": [
{
"key_stage": "InfoReceived",
"time_iso": "2023-08-14T00:00:00-05:00",
"time_utc": "2023-08-14T05:00:00Z",
"time_raw": {
"date": "2023-08-14",
"time": null,
"timezone": null
}
},
{
"key_stage": "PickedUp",
"time_iso": "2023-08-15T08:46:00-05:00",
"time_utc": "2023-08-15T12:46:00Z",
"time_raw": {
"date": "2023-08-15",
"time": "08:46:00",
"timezone": "-05:00"
}
},
{
"key_stage": "Departure",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Arrival",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "AvailableForPickup",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "OutForDelivery",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Delivered",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Returning",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Returned",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
}
],
"misc_info": {
"risk_factor": 0,
"service_type": "FedEx International Priority",
"weight_raw": "1.1 KG",
"weight_kg": "1.1",
"pieces": "1",
"dimensions": "22*20*16 CM",
"customer_number": "2459642000~270434455123~FX",
"reference_number": null,
"local_number": "270434455123",
"local_provider": "Fedex",
"local_key": 100003
},
"tracking": {
"providers_hash": 182180920,
"providers": [
{
"provider": {
"key": 100003,
"name": "Fedex",
"alias": "Fedex",
"tel": null,
"homepage": "http://www.fedex.com/",
"country": "TR"
},
"service_type": "FedEx International Priority",
"latest_sync_status": "Success",
"latest_sync_time": "2022-04-28T02:37:03Z",
"events_hash": -731027172,
"events": [
{
"time_iso": "2023-08-14T00:00:00-05:00",
"time_utc": "2023-08-14T05:00:00Z",
"time_raw": {
"date": "2023-08-14",
"time": null,
"timezone": null
},
"description": "At local FedEx facility",
"description_translation": {
"lang": "en",
"description": "At local FedEx facility"
},
"location": "ANCHORAGE, AK, US",
"stage": "InfoReceived",
"sub_status": "InfoReceived",
"address": {
"country": "US",
"state": "AK",
"city": "ANCHORAGE",
"street": null,
"postal_code": "99502",
"coordinates": {
"longitude": "35.86166",
"latitude": "104.195397"
}
}
}
]
},
{
"provider": {
"key": 1151,
"name": "Australia Post",
"alias": "Australia Post",
"tel": null,
"homepage": "http://auspost.com.au/",
"country": "AU"
},
"service_type": "International Post Express",
"latest_sync_status": "Success",
"latest_sync_time": "2022-04-12T22:12:54Z",
"events_hash": -225868020,
"events": [
{
"time_iso": "2022-03-04T15:33:00+08:00",
"time_utc": "2022-03-04T07:33:00Z",
"time_raw": {
"date": "2022-03-04",
"time": "15:33:00",
"timezone": null
},
"description": "InfoReceived",
"description_translation": {
"lang": "en",
"description": "InfoReceived"
},
"location": null,
"stage": "InfoReceived",
"sub_status": "InfoReceived",
"address": {
"country": null,
"state": null,
"city": null,
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
}
}
]
}
]
}
}
}
],
"rejected": [
{
"number": "21213123123230",
"error": {
"code": -18019910,
"message": "The carrier's value '21051' is not correct."
}
}
]
}
}
Response Explanation
Item |
Type |
Description |
---|---|---|
code | Int. | The HTTP Status code and error code. |
data | Object | The response data. |
-accepted | Object | This shows the data that has been received and processed successfully. |
--number | String | Tracking number. |
--carrier | Int. | Carrier code |
--param | String | Additional parameter like postcode, order date, etc., required by some carriers along with the tracking number. 1. Length limit: within 12 characters. 2. Only letter, number and space are allowed. 3. Date time format: yyyy-mm-dd. |
--tag | String | Custom tag. See tracking number registration for more info. |
--track_info | Object | Tracking info |
---shipping_info | Object | Location info. |
----shipper_address | Object | Location info of the origin country. |
-----country | String | Country or region (capital letter). |
-----state | String | State or province. |
-----postal_code | String | Post code. |
-----city | String | City. |
-----street | String | Street. |
-----coordinates | Object | Coordinates. |
------longitude | String | longitude. |
------latitude | String | latitude. |
----recipient_address | Object | Location info of the destination country. |
-----country | String | Country or region (capital letter). |
-----state | String | State or province. |
-----postal_code | String | Post code. |
-----city | String | City. |
-----street | String | Street. |
-----coordinates | Object | Coordinates. |
------longitude | String | longitude. |
------latitude | String | latitude. |
---latest_status | Object | The lastest status. |
----status | String | Main status. |
----sub_status | String | Sub-status. |
----sub_status_descr | String | Status description. |
---latest_event | Object | The latest event. See events set. |
---time_metrics | Object | Info related to timeliness, where estimated_delivery_date indicate a period of time. |
----days_after_order | Int. | Order Transit Time(in days) Calculation: 1. For delivered status, Order Transit Time(in days) = Delivery Date - First Event Date. 2. For non-delivered status, with tracking result, Order Transit Time(in days) = Current Date - First Event Date. 3. No tracking result, Order Transit Time(in days) = 0. |
----days_after_last_update | Int. | No Update Days: 1. For delivered, return to sender, and no result status, interval in days = 0. 2. For other cases, interval in days = Current Date - Last Event Date. |
----days_of_transit | Int. | Transit Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Transit Time(in days) = Delivery Date - Pickedup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and “InfoReceived”,Transit Time(in days) = Delivery Date - First Event Date. For non-delivered status , with tracking result: 1. With “InTransit_PickedUp”,Transit Time(in days) = Current Date - Pickup Date 2. WIthout “InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Current Date - First Event Date after "InfoReceived". 3. WIthout "InTransit_PickedUp",with "InfoReceived",and only one tracking event, Transit Time(in days) = 0. 4. Without both "InTransit_PickedUp" and "InfoReceived",Transit Time(in days) = Current Date - First Event Date. No tracking result: Transit Time(in days) = 0. |
----days_of_transit_done | Int. | Delivery Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Delivery Time(in days) = Delivery Date - Pickup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Delivery Time(in days) =Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and "InfoReceived",Delivery Time(in days) = Delivery Date - First Event Date. For non-delivered status: Delivery Time(in days) = 0. |
----estimated_delivery_date | Object | The estimiated date of delivery. It gives a range of dates. |
-----source | String | It refers to the party who provides info for "from" and "to" sections. It will show "17TRACK" when the info is provided by 17TRACK; show "Official" when the info is provided by carrier; and show "null" when the info is provided by none. |
-----from | String | The earliest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
-----to | String | The latest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
---milestone | Array | A set of date regarding each important stage of the shipping process. Purpose: Display key nodes and their occurrence sequence and time during the shipping process. Usage: Iterate through each milestone item, recommended order: InfoReceived >> PickedUp >> Departure >> Arrival >> OutForDelivery >> Delivered. (Use AvailableForPickup, Returned, Returning as needed based on specific cases) Note: If time_iso or time_utc is null, it means the carrier did not provide event description. milestone[]. key_stage can be used to query more specific event content in tracking.providers[].events[].stage. Meanings of milestone's key_stage: 1. InfoReceived : The carrier has received the order info and is about to pick up the package from the sender. 2. PickedUp : The package has been collected by the carrier. 3. Departure : The package has departed from a port. (Usually means after customs clearance.) 4. Arrival : The package has arrived at a port. (Not certain if the customs clearance is made.) 5. AvailableForPickup : The package has arrived at the pick up point of the destination. The recipient needs to go get it. 6. OutForDelivery : The package is out for delivery. 7. Delivered : The package is delivered and signed by the recipient. 8. Returned : The package was returned to the sender. 9. Returning : The package is being returned to the sender. This not always change to "Returned" even if the process is done. |
----key_stage | String | A set of all milestones. There are 9 of them. When time_iso and time_utc are populated, it means the relevent event has happened. These stages can be use to get a big picture of the shipping process. You can know the package has gone through a flow like "InfoReceived > PickedUp > Departure > Arrival > Delivered". |
----time_iso | String | 1. The time of the stage in ISO format, transfered from the local time of the carrier. If it can not be tranfered, the original time format will show instead. 2. If the upperstream carrier provide timezone info, it will be prioritize, otherwise the carrier's HQ time will be used. 3. 2022-03-02T20:43:24-06:00 means the timezone is UTC−06:00. 4.Remove the -06:00 is removed, it means the carrier's local time. 5. See this field is in tracking.providers[].provider[].events[].time_iso. |
----time_utc | String | 1. The time of the stage in UTC format, transfered from the ISO time. 2. For example: 2022-03-03T02:43:24Z. 3. See tracking.providers[].provider[].events[].time_utc. |
----time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
-----date | String | YYYY-MM-DD |
-----time | String | HH:MM:SS |
-----timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
---misc_info | Object | Package additional info. |
----risk_factor | String | Package risk factor. |
----service_type | String | Package service type |
----weight_raw | String | Original weight info. |
----weight_kg | String | Weight info in Kg. |
----pieces | String | Total pieces. |
----dimensions | String | Dimensions (length, width, height). |
----customer_number | String | The customer number of the recipient. |
----reference_number | String | A reference number. |
----local_number | String | The last-mile tracking code. |
----local_provider | String | The last-mile carrier. |
----local_key | Int. | The last-mile carrier code. |
---tracking | Object | Tracking info. |
----providers_hash | Int. | The hash value, calculated from the event content, can be used to determine if there are changes. |
----providers | Array | A set of carriers participated in the shipping process, in ascending order, with 0 being the second carrier, 1 being the first, etc. Note: When the parcel is a postal shipment, the "providers[0]" object is the destination carrier, "providers[1]" is the object is the originating carrier, " providers[0]" and "providers[1]" description, time may be duplicated. |
-----provider | Object | Carrier info |
------key | Int. | Carrier code. |
------name | String | Carrier name. |
------tel | String | Carrier phone number. |
------homepage | String | Carrier website. |
------country | String | Carrier country. |
-----service_type | String | Carrier service type. |
-----latest_sync_status | String | The latest status of data synchronization. Failure Success |
-----latest_sync_time | String | The last time of data synchronization. |
-----events_hash | Int. | The hash value of the events. |
-----events | Array | The set of events. |
------time_iso | String | The time of the event in ISO format. If there is no valid data, it shows null. |
------time_utc | String | The time of the event in UTC format. If the time_iso is null, it shows null. |
------time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
-------date | String | YYYY-MM-DD |
-------time | String | HH:MM:SS |
-------timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
------description | String | Event description. Including: time, shipping details, key status. |
------description_translation | String | Describes the translation node. |
-------description | String | Description of the translated event. |
-------lang | String | Translation language code |
------location | String | Location. |
------stage | String | Stage. |
------sub_status | String | Sub-status. |
------address | Object | Address info. |
-------country | String | Country or region. |
-------state | String | State or province. |
-------city | String | City. |
-------street | String | Street. |
-------postal_code | String | Post code. |
-------coordinates | Object | coordinates. |
--------longitude | String | longitude. |
--------latitude | String | latitude. |
-rejected | Array | Rejects the return content of the request. |
--number | String | The tracking number must conform to the tracking number format. |
--error | Object | Error message collection |
---code | Int. | Error code. |
--message | String | Error description. |
Get a push manually - POST https://api.17track.net/track/v2.2/push
- The endpoint receives a maximum of 40 tracking numbers at a single time.
- The request will put the tracking number in a queue for processing before it is pushed by the system's universal scheduler.
Example Request
curl -X POST \
--header '17token:your secret key' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]' \
https://api.17track.net/track/v2.2/push
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.17track.net/track/v2.2/push",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]",
CURLOPT_HTTPHEADER => [
"17token: your secret key",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.17track.net/track/v2.2/push"),
Headers =
{
{ "17token", "your secret key" },
},
Content = new StringContent("[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String value = "[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]";
RequestBody body = RequestBody.create(mediaType, value);
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/push")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("17token", "your secret key")
.build();
Response response = client.newCall(request).execute();
response.body();
const axios = require("axios");
const options = {
method: 'POST',
url: 'https://api.17track.net/track/v2.2/push',
headers: {
'content-type': 'application/json',
'17token': 'your secret key'
},
data: '[
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
import requests
url = "https://api.17track.net/track/v2.2/push"
payload = [
{
"number": "RR123456789CN",
"carrier": 3011
},
{
"number": "21213123123230",
"carrier": 21051
}
]
headers = {
"content-type": "application/json",
"17token": "your secret key"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
Parameter Explanation:
Parameter | Required |
Type |
Description |
---|---|---|---|
number | Yes | String | The tracking number must conform to the tracking number format. |
carrier | No | Int. | Carrier Code. If not passed in and if the tracking number can be matched to multiple carriers, it will be processed for multiple times for each carrier matched. |
Example Response
{ "code": 0, "data": { "accepted": [ { "number": "RR123456789CN", "carrier": 3011 } ] } }
Response Explanation:
Item | Description |
---|---|
code | The HTTP Status code and error code. |
data | The response data. |
-accepted | This shows the data that has been received and processed successfully. |
-rejected | This shows the tracking numbers failed to be processed. An error code will be returned. |
--number | Tracking number. |
--error | Error message collection |
---code | Error code. |
--message | Error description. |
Get Real Time Tracking Details - POST https://api.17track.net/track/v2.2/getRealTimeTrackInfo
- If the tracking number is not registered, the response result will not be saved in the current account; if the number is subscribed and the query result changes, a push (webhook) will be triggered;
- Currently, the following carriers do not support real-time query through this interface:
Carrier Name | Carrier Code |
---|---|
USPS | 21051 |
Royal Mail | 11031 |
Australia post | 1151 |
Direct Freight Express | 101066 |
DHL eCommerce US | 7047 |
DHL Global Forwarding | 100766 |
- The maximum timeout for requests to this interface is 30 seconds;
- This interface provides two query modes, each with different query times and different quota deduction rules.
cacheLevel=0: Retrieves tracking information from the carrier within the last 3 hours (default). This is the manual refresh method, commonly used by most users, and deducts 1 quota per request.
cacheLevel=1: Initiates a real-time fetch action to obtain the current tracking information from the carrier, offering the most up-to-date results. This method deducts 10 quotas per request.
Example Request
curl -X POST \
--header '17token:密钥' \
--header 'Content-Type:application/json' \
--data '[
{
"number": "RR123456789CN",
"carrier": 3011
}
]' \
https://api.17track.net/track/v2.2/getRealTimeTrackInfo
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.17track.net/track/v2.2/getRealTimeTrackInfo',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'[
{
"number": "RR123456789CN",
"carrier":3011
}
]
',
CURLOPT_HTTPHEADER => array(
'content-type: application/json',
'17token: 密钥'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.17track.net/track/v2.2/getRealTimeTrackInfo");
request.Headers.Add("content-type", "application/json");
request.Headers.Add("17token", "密钥");
var content = new StringContent("[\r\n {\r\n \"number\": \"RR123456789CN\",\r\n \"carrier\":3011\r\n }\r\n]\r\n ", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "[\r\n {\r\n \"number\": \"RR123456789CN\",\r\n \"carrier\":3011\r\n }\r\n]\r\n ");
Request request = new Request.Builder()
.url("https://api.17track.net/track/v2.2/getRealTimeTrackInfo")
.method("POST", body)
.addHeader("content-type", "application/json")
.addHeader("17token", "密钥")
.build();
Response response = client.newCall(request).execute();
const axios = require('axios');
let data = JSON.stringify([
{
"number": "RR123456789CN",
"carrier": 3011
}
]);
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://api.17track.net/track/v2.2/getRealTimeTrackInfo',
headers: {
'content-type': 'application/json',
'17token': '密钥'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://api.17track.net/track/v2.2/getRealTimeTrackInfo"
payload = json.dumps([
{
"number": "RR123456789CN",
"carrier": 3011
}
])
headers = {
'content-type': 'application/json',
'17token': '密钥'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
Request Parameter
Parameter | Required | Type | Description |
---|---|---|---|
number | Yes | String | The tracking number to register. It must conform to the tracking number format. |
param | No | String | Additional parameters such as postcode, order date, etc., required by some carriers along with the tracking number. |
carrier | No | Int. | 1. Pass in the Carrier Code if you want to specify a carrier for the tracking number. 2. Most UPU and commercial carriers can be auto-identified by our system. If no or an incorrect carrier code is provided, the system will identify the most likely carrier and return its Carrier Code. 3. If you receive a -18019903 error indicates that no carrier was found. Register the number again with a valid Carrier Code. |
final_carrier | No | Int. | Carrier Code of the last-mile carrier. (Applicable only for UPU numbers) |
auto_detection | No | Boolean | Controls carrier auto-detection. Default is 'true'. If enabled, the system will attempt to auto-detect the carrier based on the tracking number. Note: This does not always guarantee accuracy and will be ignored if a carrier parameter is provided. |
cacheLevel | No | Int. | 17TRACK offers two query modes: 0: Retrieves tracking info from the carrier within the last 3 hours (default). This is the manual refresh method , commonly used by most users, deducting 1 quota per request. 1: Initiates an immediate fetch to retrieve the most up-to-date tracking information. This method provides the latest updates, and deducts 10 quotas per request. |
Successful Response Example
{
"code": 0,
"data": {
"accepted": [
{
"number": "RR123456789CN",
"carrier": 3011,
"param": null,
"tag": "",
"track_info": {
"shipping_info": {
"shipper_address": {
"country": "CN",
"state": null,
"city": null,
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
},
"recipient_address": {
"country": "",
"state": null,
"city": null,
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
}
},
"latest_status": {
"status": "NotFound",
"sub_status": "NotFound_Other",
"sub_status_descr": null
},
"latest_event": null,
"time_metrics": {
"days_after_order": 0,
"days_of_transit": 0,
"days_of_transit_done": 0,
"days_after_last_update": 0,
"estimated_delivery_date": {
"source": null,
"from": null,
"to": null
}
},
"milestone": [],
"misc_info": {
"risk_factor": 0,
"service_type": null,
"weight_raw": null,
"weight_kg": null,
"pieces": null,
"dimensions": null,
"customer_number": null,
"reference_number": null,
"local_number": null,
"local_provider": null,
"local_key": 0
},
"tracking": {
"providers_hash": 0,
"providers": [
{
"provider": {
"key": 3011,
"name": "China Post",
"alias": "China Post 中国邮政",
"tel": "",
"homepage": "https://yjcx.ems.com.cn/",
"country": "CN"
},
"provider_lang": null,
"service_type": null,
"latest_sync_status": "Success",
"latest_sync_time": "2024-12-10T14:14:42Z",
"events_hash": 0,
"events": []
}
]
}
}
}
],
"rejected": []
}
}
Response Explanation
Item | Type | Description |
---|---|---|
code | Int. | The HTTP Status code and error code. |
data | Object | The response data. |
-accepted | Object | This shows the data that has been received and processed successfully. |
--number | String | Tracking number. |
--carrier | Int. | Carrier code |
--param | String | Additional parameters like postcode, order date, etc. |
--tag | String | Custom tag. See tracking number registration for more info. |
--track_info | Object | Tracking info |
---shipping_info | Object | Location info. |
----shipper_address | Object | Location info of the origin country. |
-----country | String | Country or region (capital letter). |
-----state | String | State or province. |
-----postal_code | String | Post code. |
-----city | String | City. |
-----street | String | Street. |
-----coordinates | Object | Coordinates. |
------longitude | String | longitude. |
------latitude | String | latitude. |
----recipient_address | Object | Location info of the destination country. |
-----country | String | Country or region (capital letter). |
-----state | String | State or province. |
-----postal_code | String | Post code. |
-----city | String | City. |
-----street | String | Street. |
-----coordinates | Object | Coordinates. |
------longitude | String | longitude. |
------latitude | String | latitude. |
---latest_status | Object | The lastest status. |
----status | String | Main status. |
----sub_status | String | Sub-status. |
----sub_status_descr | String | Status description. |
---latest_event | Object | The latest event. See events set. |
---time_metrics | Object | Info related to timeliness, where estimated_delivery_date indicate a period of time. |
----days_after_order | Int. | Order Transit Time(in days) Calculation: 1. For delivered status, Order Transit Time(in days) = Delivery Date - First Event Date. 2. For non-delivered status, with tracking result, Order Transit Time(in days) = Current Date - First Event Date. 3. No tracking result, Order Transit Time(in days) = 0. |
----days_after_last_update | Int. | No Update Days: 1. For delivered, return to sender, and no result status, interval in days = 0. 2. For other cases, interval in days = Current Date - Last Event Date. |
----days_of_transit | Int. | Transit Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Transit Time(in days) = Delivery Date - Pickedup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and “InfoReceived”,Transit Time(in days) = Delivery Date - First Event Date. For non-delivered status , with tracking result: 1. With “InTransit_PickedUp”,Transit Time(in days) = Current Date - Pickup Date 2. WIthout “InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Current Date - First Event Date after "InfoReceived". 3. WIthout "InTransit_PickedUp",with "InfoReceived",and only one tracking event, Transit Time(in days) = 0. 4. Without both "InTransit_PickedUp" and "InfoReceived",Transit Time(in days) = Current Date - First Event Date. No tracking result: Transit Time(in days) = 0. |
----days_of_transit_done | Int. | Delivery Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Delivery Time(in days) = Delivery Date - Pickup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Delivery Time(in days) =Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and "InfoReceived",Delivery Time(in days) = Delivery Date - First Event Date. For non-delivered status: Delivery Time(in days) = 0. |
----estimated_delivery_date | Object | The estimiated date of delivery. It gives a range of dates. |
-----source | String | It refers to the party who provides info for "from" and "to" sections. It will show "17TRACK" when the info is provided by 17TRACK; show "Official" when the info is provided by carrier; and show "null" when the info is provided by none. |
-----from | String | The earliest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
-----to | String | The latest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
---milestone | Array | A set of date regarding each important stage of the shipping process. Purpose: Display key nodes and their occurrence sequence and time during the shipping process. Usage: Iterate through each milestone item, recommended order: InfoReceived >> PickedUp >> Departure >> Arrival >> OutForDelivery >> Delivered. (Use AvailableForPickup, Returned, Returning as needed based on specific cases) Note: If time_iso or time_utc is null, it means the carrier did not provide event description. milestone[]. key_stage can be used to query more specific event content in tracking.providers[].events[].stage. Meanings of milestone's key_stage: 1. InfoReceived : The carrier has received the order info and is about to pick up the package from the sender. 2. PickedUp : The package has been collected by the carrier. 3. Departure : The package has departed from a port. (Usually means after customs clearance.) 4. Arrival : The package has arrived at a port. (Not certain if the customs clearance is made.) 5. AvailableForPickup : The package has arrived at the pick up point of the destination. The recipient needs to go get it. 6. OutForDelivery : The package is out for delivery. 7. Delivered : The package is delivered and signed by the recipient. 8. Returned : The package was returned to the sender. 9. Returning : The package is being returned to the sender. This not always change to "Returned" even if the process is done. |
----key_stage | String | A set of all milestones. There are 9 of them. When time_iso and time_utc are populated, it means the relevent event has happened. These stages can be use to get a big picture of the shipping process. You can know the package has gone through a flow like "InfoReceived > PickedUp > Departure > Arrival > Delivered". |
----time_iso | String | 1. The time of the stage in ISO format, transfered from the local time of the carrier. If it can not be tranfered, the original time format will show instead. 2. If the upperstream carrier provide timezone info, it will be prioritize, otherwise the carrier's HQ time will be used. 3. 2022-03-02T20:43:24-06:00 means the timezone is UTC−06:00. 4.Remove the -06:00 is removed, it means the carrier's local time. 5. See this field is in tracking.providers[].provider[].events[].time_iso. |
----time_utc | String | 1. The time of the stage in UTC format, transfered from the ISO time. 2. For example: 2022-03-03T02:43:24Z. 3. See tracking.providers[].provider[].events[].time_utc. |
----time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
-----date | String | YYYY-MM-DD |
-----time | String | HH:MM:SS |
-----timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
---misc_info | Object | Package additional info. |
----risk_factor | String | Package risk factor. |
----service_type | String | Package service type |
----weight_raw | String | Original weight info. |
----weight_kg | String | Weight info in Kg. |
----pieces | String | Total pieces. |
----dimensions | String | Dimensions (length, width, height). |
----customer_number | String | The customer number of the recipient. |
----reference_number | String | A reference number. |
----local_number | String | The last-mile tracking code. |
----local_provider | String | The last-mile carrier. |
----local_key | Int. | The last-mile carrier code. |
---tracking | Object | Tracking info. |
----providers_hash | Int. | The hash value, calculated from the event content, can be used to determine if there are changes. |
----providers | Array | A set of carriers participated in the shipping process, in ascending order, with 0 being the second carrier, 1 being the first, etc. Note: When the parcel is a postal shipment, the "providers[1]" object is the destination carrier, "providers[0]" is the object is the originating carrier, " providers[0]" and "providers[1]" description, time may be duplicated. |
-----provider | Object | Carrier info |
------key | Int. | Carrier code. |
------name | String | Carrier name. |
------tel | String | Carrier phone number. |
------homepage | String | Carrier website. |
------country | String | Carrier country. |
-----service_type | String | Carrier service type. |
-----latest_sync_status | String | The latest status of data synchronization. Failure Success |
-----latest_sync_time | String | The last time of data synchronization. |
-----events_hash | Int. | The hash value of the events. |
-----events | Array | The set of events. |
------time_iso | String | The time of the event in ISO format. If there is no valid data, it shows null. |
------time_utc | String | The time of the event in UTC format. If the time_iso is null, it shows null. |
------time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
-------date | String | YYYY-MM-DD |
-------time | String | HH:MM:SS |
-------timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
------description | String | Event description. Including: time, shipping details, key status. |
------description_translation | String | Describes the translation node. |
-------description | String | Description of the translated event. |
-------lang | String | Translation language code |
------location | String | Location. |
------stage | String | Stage. |
------sub_status | String | Sub-status. |
------address | Object | Address info. |
-------country | String | Country or region. |
-------state | String | State or province. |
-------city | String | City. |
-------street | String | Street. |
-------postal_code | String | Post code. |
-------coordinates | Object | coordinates. |
--------longitude | String | longitude. |
--------latitude | String | latitude. |
-rejected | Array | Rejects the return content of the request. |
--number | String | The tracking number must conform to the tracking number format. |
--error | Object | Error message collection |
---code | Int. | Error code. |
--message | String | Error description. |
Webhook
What is a webhook?
A webhook is not part of 17TRACK API. It's an an interface created by you in the form of a URL to receive the tracking status pushed by 17TRACK Tracking API.
Set up your webhook for 17TRACK Tracking API
Step 1 Create your Webhook URL.
- This should be done based on your own system or the platform you use. The below is a sample code in JAVA that may be helpful to you:
@RestController
class WebhookController {
WebhookController() {
}
@PostMapping("/notify")
void notify(@RequestBody String body) {
// body will be used to receive the push message
}
}
Step 2 Paste your Webhook URL to 17TRACK dashboard.
- Log in to your API account and go to https://api.17track.net/admin/settings. Click on the [Settings] button on the left, fill in the URL from step 1 on the right and click on the [Save] button.
Step 3 Do a quick test and see if it works.
- Go to the [WebHook test] section on the left, paste your Webhook URL to he input box and click on the [Test] button. If a notification in green pops up saying “Operation Done”, then it works. You can get a testing Webhook URL here https://webhook.site.
How does the push work?
- Webhook notifications are sent based on a queue machanism. It is recommended that you also use a queue to process the info received.
- Each webhook notification contains the complete info of a tracking number.
- If a 200 HTTP Status code is returned, the request was processed successfully.
- Any HTTP Status code other than 200 is considered as a failed push.
- If a notification push is failed, the system will retry another 3 times for the current package status. When it enters the next status, the system will follow the same process to push the notification and so on. See below for the retry interval:
Times of attempts | Times of retries | Retry interval (sec) |
---|---|---|
1 | - | - |
2 | 1 | 600 |
3 | 2 | 1800 |
4 | 3 | 3600 |
Notification Status & Content
TRACKING_STOPPED
- This means the number is no longer updated and no more tracking updated notification will be pushed.
- A "tracking stopped" message will be pushed if the tracking is stopped due to the system mechanism.
- You can use the retrack endpoint to restart the tracking.
Example Push
{ "event": "TRACKING_STOPPED", "data": { "number": "RR123456789CN", "carrier": 3011, "param": null, "tag": "" } }
Response Explanation:
Item | Description |
---|---|
event | Notification status. |
-number | The tracking number of which the auto-tracking process is stopped. |
-carrier | The carrier of the tracking number. |
TRACKING_UPDATED
- When the tracking number is registered successfully, and if there is a change to the package status, this notification will be triggered immediately.
Example Headers
"content-type",
"content-length",
"sign":"9a44ab6... ...4b4bf5",
... ...
Example Message Body
{
"event": "TRACKING_UPDATED",
"data": {
"number": "RR123456789CN",
"carrier": 3011,
"param": "518000",
"tag": "myID",
"track_info": {
"shipping_info": {
"shipper_address": {
"country": "CN",
"state": "GD",
"city": "SHENZHEN",
"street": "HARTFORD CT DISTRIBUTION CENTER",
"postal_code": "518000",
"coordinates": {
"longitude": "114.085947",
"latitude": "22.547"
}
},
"recipient_address": {
"country": null,
"state": null,
"city": null,
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
}
},
"latest_status": {
"status": "InTransit",
"sub_status": "InTransit_Other",
"sub_status_descr": null
},
"latest_event": {
"time_iso": "2022-03-02T20:43:24-06:00",
"time_utc": "2022-03-03T02:43:24Z",
"time_raw": {
"date": "2022-03-02",
"time": "20:43:24",
"timezone": "-06:00"
},
"description": "The plane entered the port",
"description_translation": {
"lang": "en",
"description": "The plane entered the port"
},
"location": "NJ",
"stage": "Delivered",
"sub_status": "Delivered_Other",
"address": {
"country": null,
"state": null,
"city": null,
"street": null,
"postal_code": null,
"coordinates": {
"longitude": null,
"latitude": null
}
}
},
"time_metrics": {
"days_after_order": 45,
"days_of_transit": 45,
"days_of_transit_done": 0,
"days_after_last_update": 17,
"estimated_delivery_date": {
"source":"Official",
"from": "2022-03-02T18:43:24-06:00",
"to": "2022-03-03T19:43:24-06:00"
}
},
"milestone": [
{
"key_stage": "InfoReceived",
"time_iso": "2023-08-14T00:00:00-05:00",
"time_utc": "2023-08-14T05:00:00Z",
"time_raw": {
"date": "2023-08-14",
"time": null,
"timezone": null
}
},
{
"key_stage": "PickedUp",
"time_iso": "2023-08-15T08:46:00-05:00",
"time_utc": "2023-08-15T12:46:00Z",
"time_raw": {
"date": "2023-08-15",
"time": "08:46:00",
"timezone": "-05:00"
}
},
{
"key_stage": "Departure",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Arrival",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "AvailableForPickup",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "OutForDelivery",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Delivered",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Returning",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
},
{
"key_stage": "Returned",
"time_iso": null,
"time_utc": null,
"time_raw": {
"date": null,
"time": null,
"timezone": null
}
}
],
"misc_info": {
"risk_factor": 0,
"service_type": "FedEx International Priority",
"weight_raw": "1.1 KG",
"weight_kg": "1.1",
"pieces": "1",
"dimensions": "22*20*16 CM",
"customer_number": "2459642000~270434455123~FX",
"reference_number": null,
"local_number": "270434455123",
"local_provider": "Fedex",
"local_key": 100003
},
"tracking": {
"providers_hash": 2067301750,
"providers": [
{
"provider": {
"key": 3011,
"name": "China Post",
"alias": "China Post",
"tel": null,
"homepage": "http://www.17track.net",
"country": "CN"
},
"service_type": "International Priority",
"latest_sync_status": "Success",
"latest_sync_time": "2022-06-09T05:46:31Z",
"events_hash": -227928244,
"events": [
{
"time_iso": "2023-08-14T00:00:00-05:00",
"time_utc": "2023-08-14T05:00:00Z",
"time_raw": {
"date": "2023-08-14",
"time": null,
"timezone": null
},
"description": "At local FedEx facility",
"description_translation": {
"lang": "en",
"description": "At local FedEx facility"
},
"location": "ANCHORAGE, AK, US",
"stage": null,
"sub_status": null,
"address": {
"country": "US",
"state": "AK",
"city": "ANCHORAGE",
"street": null,
"postal_code": "99502",
"coordinates": {
"longitude": "35.86166",
"latitude": "104.195397"
}
}
}
]
}
]
}
}
}
}
Response Explanation:
Item |
Type |
Description |
---|---|---|
event | String | Notification status. |
data | Object | The response data. |
-number | String | Tracking number. |
-carrier | Int. | Carrier code |
-param | String | Additional parameter like postcode, order date, etc., required by some carriers along with the tracking number. 1. Length limit: within 10 characters. 2. Only letter, number and space are allowed. 3. Date time format: yyyy-mm-dd. |
-tag | String | Custom tag. See tracking number registration for more info. |
-track_info | Object | Tracking info |
--shipping_info | Object | Location info. |
---shipper_address | Object | Location info of the origin country. |
----country | String | Country or region (capital letter). |
----state | String | State or province. |
----postal_code | String | Post code. |
----city | String | City. |
----street | String | Street. |
----coordinates | Object | Coordinates. |
-----longitude | String | longitude. |
-----latitude | String | latitude. |
---recipient_address | Object | Location info of the destination country. |
----country | String | Country or region (capital letter). |
----state | String | State or province. |
----postal_code | String | Post code. |
----city | String | City. |
----street | String | Street. |
----coordinates | Object | Coordinates. |
-----longitude | String | longitude. |
-----latitude | String | latitude. |
--latest_status | Object | The lastest status. |
---status | String | Main status. |
---sub_status | String | Sub-status. |
---sub_status_descr | String | Status description. |
--latest_event | Object | The latest event. See events set. |
--time_metrics | Object | Info related to timeliness, where estimated_delivery_date indicate a period of time. |
---days_after_order | Int. | Order Transit Time(in days) Calculation: 1. For delivered status, Order Transit Time(in days) = Delivery Date - First Event Date. 2. For non-delivered status, with tracking result, Order Transit Time(in days) = Current Date - First Event Date. 3. No tracking result, Order Transit Time(in days) = 0. |
---days_after_last_update | Int. | No Update Days: 1. For delivered, return to sender, and no result status, interval in days = 0. 2. For other cases, interval in days = Current Date - Last Event Date. |
---days_of_transit | Int. | Transit Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Transit Time(in days) = Delivery Date - Pickedup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and “InfoReceived”,Transit Time(in days) = Delivery Date - First Event Date. For non-delivered status , with tracking result: 1. With “InTransit_PickedUp”,Transit Time(in days) = Current Date - Pickup Date 2. WIthout “InTransit_PickedUp",with "InfoReceived",Transit Time(in days) = Current Date - First Event Date after "InfoReceived". 3. WIthout "InTransit_PickedUp",with "InfoReceived",and only one tracking event, Transit Time(in days) = 0. 4. Without both "InTransit_PickedUp" and "InfoReceived",Transit Time(in days) = Current Date - First Event Date. No tracking result: Transit Time(in days) = 0. |
---days_of_transit_done | Int. | Delivery Time(in days) Calculation: For delivered status: 1. With "InTransit_PickedUp",Delivery Time(in days) = Delivery Date - Pickup Date 2. Without "InTransit_PickedUp",with "InfoReceived",Delivery Time(in days) =Delivery Date - First Event Date after "InfoReceived". 3. Without both "InTransit_PickedUp" and "InfoReceived",Delivery Time(in days) = Delivery Date - First Event Date. For non-delivered status: Delivery Time(in days) = 0. |
---estimated_delivery_date | Object | The estimiated date of delivery. It gives a range of dates. |
----source | String | It refers to the party who provides info for "from" and "to" sections. It will show "17TRACK" when the info is provided by 17TRACK; show "Official" when the info is provided by carrier; and show "null" when the info is provided by none. |
----from | String | The earliest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
----to | String | The latest estimated date of delivery (ISO format). E.g 2021-09-01T08:00:54-05:00 |
---milestone | Array | A set of date regarding each important stage of the shipping process. Purpose: Display key nodes and their occurrence sequence and time during the shipping process. Usage: Iterate through each milestone item, recommended order: InfoReceived >> PickedUp >> Departure >> Arrival >> OutForDelivery >> Delivered. (Use AvailableForPickup, Returned, Returning as needed based on specific cases) Note: If time_iso or time_utc is null, it means the carrier did not provide event description. milestone[]. key_stage can be used to query more specific event content in tracking.providers[].events[].stage. Meanings of milestone's key_stage: 1. InfoReceived : The carrier has received the order info and is about to pick up the package from the sender. 2. PickedUp : The package has been collected by the carrier. 3. Departure : The package has departed from a port. (Usually means after customs clearance.) 4. Arrival : The package has arrived at a port. (Not certain if the customs clearance is made.) 5. AvailableForPickup : The package has arrived at the pick up point of the destination. The recipient needs to go get it. 6. OutForDelivery : The package is out for delivery. 7. Delivered : The package is delivered and signed by the recipient. 8. Returned : The package was returned to the sender. 9. Returning : The package is being returned to the sender. This not always change to "Returned" even if the process is done. |
---key_stage | String | A set of all milestones. There are 9 of them. When time_iso and time_utc are populated, it means the relevent event has happened. These stages can be use to get a big picture of the shipping process. You can know the package has gone through a flow like "InfoReceived > PickedUp > Departure > Arrival > Delivered". |
---time_iso | String | 1. The time of the stage in ISO format, transfered from the local time of the carrier. If it can not be tranfered, the original time format will show instead. 2. If the upperstream carrier provide timezone info, it will be prioritize, otherwise the carrier's HQ time will be used. 3. 2022-03-02T20:43:24-06:00 means the timezone is UTC−06:00. 4.Remove the -06:00 is removed, it means the carrier's local time. 5. See this field is in tracking.providers[].provider[].events[].time_iso. |
---time_utc | String | 1. The time of the stage in UTC format, transfered from the ISO time. 2. For example: 2022-03-03T02:43:24Z. 3. See tracking.providers[].provider[].events[].time_utc. |
---time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
----date | String | YYYY-MM-DD |
----time | String | HH:MM:SS |
----timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
--misc_info | Object | Package additional info. |
---risk_factor | String | Package risk factor. |
---service_type | String | Package service type |
---weight_raw | String | Original weight info. |
---weight_kg | String | Weight info in Kg. |
---pieces | String | Total pieces. |
---dimensions | String | Dimensions (length, width, height). |
---customer_number | String | The customer number of the recipient. |
---reference_number | String | A reference number. |
---local_number | String | The last-mile tracking code. |
---local_provider | String | The last-mile carrier. |
---local_key | Int. | The last-mile carrier code. |
--tracking | Object | Tracking info. |
---providers_hash | Int. | The hash value, calculated from the event content, can be used to determine if there are changes. |
---providers | Array | A set of carriers participated in the shipping process, in ascending order, with 0 being the second carrier, 1 being the first, etc. Note: When the parcel is a postal shipment, the "providers[0]" object is the destination carrier, "providers[1]" is the object is the originating carrier, " providers[0]" and "providers[1]" description, time may be duplicated. |
----provider | Object | Carrier info |
-----key | Int. | Carrier code. |
-----name | String | Carrier name. |
-----tel | String | Carrier phone number. |
-----homepage | String | Carrier website. |
-----country | String | Carrier country. |
----service_type | String | Carrier service type. |
----latest_sync_status | String | The latest status of data synchronization. Failure Success |
----latest_sync_time | String | The last time of data synchronization. |
----events_hash | Int. | The hash value of the events. |
----events | Array | The set of events. |
-----time_iso | String | The time of the event in ISO format. If there is no valid data, it shows null. |
-----time_utc | String | The time of the event in UTC format. If the time_iso is null, it shows null. |
-----time_raw | Object | Original date & time info provided by carrier: 1. Three groups of data, including YYYY-MM-DD, HH:MM:SS, Timezone. 2. It will show "null" if carrier does not provide any data. |
------date | String | YYYY-MM-DD |
------time | String | HH:MM:SS |
------timezone | String | Timezone (If it shows "null" in Timezone section but a valid date & time in time_iso, it indicates that the Timezone info is added by 17TRACK.) |
-----description | String | Event description. Including: time, shipping details, key status. |
-----description_translation | String | Describes the translation node. |
------description | String | Description of the translated event. |
------lang | String | Translation language code |
-----location | String | Location. |
-----stage | String | Stage. |
-----sub_status | String | Sub-status. |
-----address | Object | Address info. |
------country | String | Country or region. |
------state | String | State or province. |
------city | String | City. |
------street | String | Street. |
------postal_code | String | Post code. |
------coordinates | Object | coordinates. |
-------longitude | String | longitude. |
-------latitude | String | latitude. |
Create and Verify the Signature
To make sure the data you receive comes from 17TRACK, you can create a signiture by concatenating certain info given by each push notification and calculate the SHA256 value. Then you can verify that signiture as told in the Verification section below.
- The info needed to create the signature is in the sign attribute of the request header.
- The info needed to create the signature should not be changed, or the result can be different, causing the verification to fail.
Step 1 Prep the content.
Concatenate the original notification message and the API key with "/":
- The notification message:
{"event":"TRACKING_UPDATED","data":{"number":"RR123456789CN", "carrier":3011,"tag":null}}
- The security key:
After the concatenation, the result should look like this:123456ABCDEF
{"event":"TRACKING_UPDATED","data":{"number":"RR123456789CN","carrier":3011,"tag":null}}/123456ABCDEF
Step 2 Calculate SHA256.
Generate the signature by using SHA256 hex encoding. You can see a sample code in Java here:
/**
* requestText {String} The notification message
* key {String} The security key
* return {String} The signature returned
*/
private String getGeneratedSignature(String requestText, String key) throws NoSuchAlgorithmException {
String src = requestText + "/" + key;
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(src.getBytes(StandardCharsets.UTF_8));
BigInteger number = new BigInteger(1, hash);
StringBuilder hexString = new StringBuilder(number.toString(16));
while (hexString.length() < 64) {
hexString.insert(0, '0');
}
return hexString.toString();
}
Step 3 Compare the result.
If the calculated value is the same as the value returned, it means the data is coming from 17TRACK.