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)

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.
email 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.
--email String Email
--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
--email String Email
--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 "/":

  1. The notification message:
    {"event":"TRACKING_UPDATED","data":{"number":"RR123456789CN", "carrier":3011,"tag":null}}
    
  2. The security key:
    123456ABCDEF
    
    After the concatenation, the result should look like this:
    {"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.