UPS Tracking API - JSON body format?

ups
15,004

Solution 1

Posting the answer to my own question answered by UPS support.

You'll POST the following json as the body content to the following API endpoint:

https://onlinetools.ups.com/json/Track

{
  "Security": {
    "UsernameToken": {
      "Username": "ups_username_here",
      "Password": "ups_password_here"
    },
    "UPSServiceAccessToken": {
      "AccessLicenseNumber": "ups_access_license_number_here"
    }
  },
  "TrackRequest": {
    "Request": {
      "RequestAction": "Track",
      "RequestOption": "activity"
    },
    "InquiryNumber": "1Z202Y36A898759591"
  }
}

Solution 2

On https://www.ups.com/track/api/Track/GetStatus you can post a json like

{
  "Locale": "da_DK",
  "TrackingNumber": ["enter your number here" ]
}

and you'll get a nice json structure back showing the current and previous location of the parcel

If you post multiple trackingnumbers, you only gets the summary for each parcel.

Solution 3

Here is the PHP code that I used to make the request, using cURL:

<?php

$url = 'https://wwwcie.ups.com/rest/Track'; // TEST
// $url = 'https://onlinetools.ups.com/rest/Track'; // PROD

$ups_array = array(
    'UPSSecurity' => array(
        'UsernameToken' => array(
            'Username' => 'ups_username_here',
            'Password' => 'ups_password_here'
        ),
        'ServiceAccessToken' => array(
            'AccessLicenseNumber' => 'ups_access_license_number_here'
        )
    ),
    'TrackRequest' => array(
        'Request' => array(
            'RequestOption' => 1,
            'TransactionReference' => array(
                'CustomerContext' => 'Test 001'
            )
        ),
        'InquiryNumber' => 'ups_package_tracking_number_here' //'1ZE1XXXXXXXXXXXXXX'
    )
);

$params = json_encode($ups_array);  // TURN THE ARRAY INTO JSON

$results_json = scrape_page($url, $params);  // POST TO THE API

$results = json_decode($results_json, true);  // DECODE THE JSON AND TURN IT INTO AN ARRAY

print "<PRE><FONT COLOR=RED>"; print_r($results); print "</FONT></PRE>";

Then, for the actual cURL function, I have this:

function scrape_page($url, $params) {

    $headers = array();
    $headers[] = 'Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept';
    $headers[] = 'Access-Control-Allow-Methods: POST';
    $headers[] = 'Access-Control-Allow-Origin: *';
    $headers[] = 'Content-Type: application/json';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,5);
    curl_setopt($ch, CURLOPT_TIMEOUT, 45);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $response = curl_exec($ch);

    // CHECK TO SEE IF WE GOT AN ERROR  
    // IF SO, FORMAT IT LIKE THIS   ::28::Operation timed out afterseconds  
    if ((curl_errno($ch)) && (curl_errno($ch) != 0)) {
        $response = "::".curl_errno($ch)."::".curl_error($ch);
    }

    // SEND THE RESPONSE BACK TO THE SCRIPT
    return $response;

}
Share:
15,004
Dan
Author by

Dan

Updated on June 16, 2022

Comments

  • Dan
    Dan about 2 years

    According to the latest release of the UPS developer kit documentation "Tracking Web Services Developers Guide - January 04, 2016" the tracking API can be accessed via REST / JSON. However, there is very little information within their PDF documentation about the JSON side of things both in the PDF and on the interwebs. I can't figure out for the life of me the correct body to pass and each time I get a "The request is not well-formed or the operation is not defined. Review for errors before re-submitting." error back. There is years worth of info on the XML / SOAP side of things, but I'd love to use JSON on this particular project. Anyone have any experience with this new feature of their API and what the JSON body should look like? The JSON validates properly, but obviously isn't what UPS is looking for.

    {
    	"UPSSecurity": {
    		"UsernameToken": {
    			"Username": " userHere",
    			"Password": " passHere"
    		}
    	},
    	"ServiceAccessToken": {
    		"AccessLicenseNumber": "licNoHere"
    	},
    	"Request": {
    		"RequestOption": "15"
    	},
    	"InquiryNumber": "1Z12345E0291980793",
    	"TrackingOption": "02"
    }

  • djack109
    djack109 almost 8 years
    But how do you make the request in the first place ?
  • Dan
    Dan almost 8 years
    @djack109 I added the API endpoint and POST method to the answer.
  • djack109
    djack109 almost 8 years
    Thanks for that. But how do you actually get the data to that URL. If POST data what's the form field name(s), if GET (URL) Data whats the querystring ?
  • leoger
    leoger over 7 years
    There are no form fields. In the general sense, POST just means you are sending some data in the body of the HTTP request. It can be XML, or JSON, or the contents of an arbitrary file you are uploading, but since url-encoded form data is so popular, many tools (e.g. Postman) make it look like doing a POST with form field names and values is its own special thing and/or the only way to do POST. It's not. I hope this helps!
  • John Rausch
    John Rausch over 7 years
    @djack109 just imagine HTTP requests as (ironically) mail or a package. There is an address (url) and then the contents inside (headers, body, etc). It is sometimes confusing when you learn how to send a form before you actually learn what an HTTP request is. When you set up a form and send it whether via ajax, or old fashioned html form the browser is just like "Alright im gonna take this info from the user bundle it up into a package and send it to this url". Like regular mail or a package there are many different ways to bundle and send it JSON, XML, etc. rve.org.uk/dumprequest
  • Chris78
    Chris78 almost 4 years
    This was working perfectly for us until Sept. 15, 2020, when the UPS server startet responding with HTTP 401 "unauthorized".
  • Chris78
    Chris78 almost 4 years
    But here is the solution: Make a GET request first and extract the value of the Cookie named 'X-XSRF-TOKEN-ST' from the Cookie jar. Now take that value and add it as 'X-XSRF-TOKEN' to the headers of your POST request, which should work again now. (Note the difference of the Cookie's name (...-ST) and the name in the request header.)