• As you might expect for a government organization, USPS has an old-school XML API that is publicly available.

    In this short update I'll show you how to track a package using the USPS tracking API.

    The first step is registering for a free developer account with USPS.

    After registration, there's a short wait and you'll likely receive an email with a user ID that may look something like "123ORGNAME4567". USPS doesn't use anything fancy like API keys - your User ID is your API key.

    USPS Tracking API with NodeJs

    Using NodeJs, here's how you might track a package:

    const got = require('got')
    const xml2json = require('xml2json')
    
    const track = async () => {
      const BASE_URI = 'http://production.shippingapis.com/ShippingAPI.dll?API=TrackV2'
      const xml = xml2json.toXml({
        TrackRequest: {
          USERID: process.env.USPS_USER_ID
          TrackID: [{ID: process.env.TEST_TRACKING_NUMBER}]
        }
      })
      let { body } = await got(`${BASE_URI}&XML=${encodeURIComponent(xml)}`)
      let data = JSON.parse(xml2json.toJson(body))
      return data
    }
    
    track().then(console.log.bind(console))

    In the above code snippet, I'm using got but you could just as easily use node-fetch. 

    To make requests against USPS' API, you essentially need to provide URL-encoded xml in the query string. So, for example:

    {
      TrackRequest: {
        USERID: "XXXXX",
        TrackId: [{ID: "92748999984327000003259997"}]
      }
    }

    Becomes the following with xml2json conversion:

    <TrackRequest USERID="XXXXX">
      <TrackId ID="92748999984327000003259997"></TrackId>
    </TrackRequest> 

    Using USPS' Postal Code API

    Here's how you might perform zip code lookups using the USPS Postal Code API.

    const got = require('got')
    const xml2json = require('xml2json')
    
    const postalCodeLookup = async (zipCode) => { 
      const BASE_URI = 'http://production.shippingapis.com/ShippingAPITest.dll?API=CityStateLookup'
      const xml = `
      <CityStateLookupRequest USERID="XXXXX">
        <ZipCode ID="0">
          <Zip5>${zipCode}</Zip5>
        </ZipCode>
      </CityStateLookupRequest>
      `
      const url = `${BASE_URI}&XML=${encodeURIComponent(xml)}`
      let { body } = await got(url)
      return JSON.parse(xml2json.toJson(body))
    }
    
    postalCodeLookup(99501).then(console.log.bind(console))

    Further Reading