DEV Community

Matthew Watkins
Matthew Watkins

Posted on

Hacking in everyday life (fun with the Sprint API)

Let me explain the situation I found myself in last week:

If you didn't already know, Sprint is offering a free year of unlimited service through the end of July if you port your non-Sprint number to them. It's a great deal, but if you are not a Verizon customer, they really make you work for it. If you're with a smaller carrier, the free years page will probably say you are ineligible, even if you have an eligible type of device. That's because Sprint maintains its own database of phones with some indicator on each record saying whether the phone is on the Sprint network or not (you heard me right: a database of phones that are not on their network). So, if your carrier (like mine) has not told Sprint that your phone is not on the Sprint network, the Sprint system assumes you are ineligible for the offer.

The solution is to create a support case with Sprint to get your device info (WiFi MAC address, IMEI number, phone number, make/model, and current carrier) added to that database. From the experience of family members who tried this, I know it would take up to three days for the information to get processed into the database and reflected on the free year page, and potentially longer for me to get the email from Sprint saying everything is hunky-dory. But time was of the essence, so I would have to check the free year page every few hours to try and find out when the offer was available for each of the devices I wanted to port. What a hassle!

This is where being a developer comes in handy.

I fired up my trusty Postman Interceptor Chrome extension and fired off a query for my still-ineligible phone. And there in the traffic history, I saw an AJAX HTTP request to a promising-looking endpoint that returned some promising-looking JSON:

    "errors": [
            "errorCode": "COULD_NOT_VALIDATE_SERIAL_NUMBER",
            "errorMessage": "Server.704:NMS returned status_code=49, status_text=INVALID_PHONE_OWNERSHIP: Phone owner can not be PLBL."
Enter fullscreen mode Exit fullscreen mode

The request was a GET, but it was pretty gnarly: all sorts of message IDs and tokens and timestamps. Luckily, Postman makes modifying and replaying it easy. So I started stripping off headers to see which ones I could sacrifice. Fortunately, most of the headers my browser had sent turned out to be unnecessary, and of the remaining, required headers, none were actually validated for accuracy-- the Sprint API just requires some value in those fields. At the end of the day, I could trim the entire HTTP request down to this (where xxxxxxxxxxxx represent the IMEI of the device I wanted to query):

GET /api/digital/byod/v1/foreign-device/xxxxxxxxxxxx HTTP/1.1
messageid: 1000
enterprisemessageid: ECMW593313374
messagedatetimestamp: 2017-07-19T22:56:59
applicationuserid: LVO
applicationid: LVO
Enter fullscreen mode Exit fullscreen mode

Awesome. But it's still tedious to have to do this manually every few hours. Time to automate it. I could have set up a chron job on my machine for this, but this is actually a perfect opportunity to bring in my good friend Google Apps Script. I created a new script and wrote the following, simple function and setup a trigger to have Google run it every 15-minutes:

function run() {
  if (isReady('xxxxxxxxxxxx')) {
    GmailApp.sendEmail('', 'YOUR PHONE IS IN THE DB NOW!', 'Go sign up for your free year');
    // Delete the 15-minute trigger I manually created earlier so I don't get spammed
  } else {
    Logger.log('The phone is NOT in the DB'); 

function isReady(imei) {
  Logger.log('Calling the Sprint API');
  var responseText = UrlFetchApp.fetch('' + imei, {
    'method': 'get',
    'headers': {
      'messageid': '1000',
      'enterprisemessageid': 'ECMW593313374',
      'messagedatetimestamp': '2017-07-19T22:56:59',
      'applicationuserid': 'LVO',
      'applicationid': 'LVO'
    'muteHttpExceptions': true

  // Log the response from the API

  // Parse it and return whether the object exists and has no errors
  var response = JSON.parse(responseText);
  return response && !response.errors;
Enter fullscreen mode Exit fullscreen mode

I received an email the next day from my script, informing me that I could now pounce on the free year plan. I figured I must have had a bug in the program, so I checked the logs. And there was the last logged API response, happily confirming that I was indeed now eligible for 365 days of unlimited LTE:

  "byodDetails": {
    "serialNo": "xxxxxxxxxxxx",
    "deviceSKU": "yyyyyyyyyyyyy",
    "netCompatibility": null,
    "iccId": null,
    "simKitInfo": [
        "simSKU": "zzzzzzzzzzzzzzz",
        "simPartNumber": "aaaaaaaaaaaa",
        "simPriority": "1",
        "simSKUPricingInfo": {
          "finalPrice": 2.99,
          "basePrice": 2.99
Enter fullscreen mode Exit fullscreen mode

The point I want to make is that setting up Postman, playing with the request, and writing my Google Apps Script took all of one hour. One hour to automate what would have been a tedious, multi-day process of manual verification for each of my household's devices each day.

It got me wondering: what else can I hack? What other APIs are out there? Where else can I write a bit of code and get a few hours of my life back?

What in your life can you automate?

This post originally appeared on Another Dev Blog

Discussion (1)

andy profile image
Andy Zhao (he/him) • Edited on

This is great! I love reading stuff like this, where someone cuts through the red tape and solves their own problem. Makes me really excited to be a developer in this day and age.

While I didn't automate anything, I did do something similar. I have a Logitech G400s mouse that I used for a long time. The back and forward buttons didn't work on macOS/OS X though, and Logitech didn't have good support or drivers for macOS. I downloaded some software called USB Overdrive, and it allowed me to remap the buttons to run an AppleScript (script). After about 30 minutes of figuring out the really poorly documented syntax, I managed to get my buttons to work!

It was funny though; I only needed the buttons to work on Chrome, and I realized that if I hit them on a different window or a different app, it would go back/forward one page, even though I wasn't focused on that window. Figured out some more AppleScript, specifically for Chrome, and then bam it worked like a charm. Then I got back to my regularly scheduled programming (no pun intended).