Swisher, Diamond
VooDoo Ranger Juicy Haze IPA
I recently needed TSA Pre-check within one week (which happened to be the week of Thanksgiving 2018). Long story short, I used Python's request
module to check for a new appointment, the schedule
module to do this job every 2 minutes, and then sent a notification to twitter each time a newer appointment was found. Sure enough, a same-day appointment popped up and notified me, so I was able to have my interview within two hours.
Why not create a bot?
This birthed the @EntryGlobal Bot on Twitter - a Bot that checks for available appointments in a given airport. After many twitter API violations, here is how I created the bot:
Note: this tutorial assumes you've already completed the Global Entry Application and ready to schedule an interview
Step 1: Identify the GET request
No thrills here – I use Chrome's network tab (in developer tools) to find the GET request with parameters that match my location. You must visit the scheduler page in order to find the correct GET request. Here is what I get for Atlanta Airport:

Take note of the Request URL
that shows as a GET
after each time a location is chosen. In my example, I've chosen Atlanta Airport, so a GET
request was sent in URL form as https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=1&locationId=5182&minimum=1
notice the query on the schedulerapi with locationId of 5182 – jot this down for later
Step 2: Prove to yourself that it's gonna work
I like to use iPython
while writing code, so how 'bout you fire up an iPython
session to make sure our endpoint returns data.
remember to install iPython if it's not already in your environment
In [1]: import requests
In [2]: res = requests.get('https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=1&locationId={}&minimum=1'.format(5181))
In [3]: res.text
Out[3]: u'[ {\n "locationId" : 5181,\n "startTimestamp" : "2019-01-31T09:45",\n "endTimestamp" : "2019-01-31T10:00",\n "active" : true,\n "duration" : 15\n} ]'
We're now able to quickly get the next available startTimeStamp
(aka appointment) for locationId 5182
without having to use the UI! Now what should we do?
- Schedule the check as a frequent task
- Establish a notification system with compliant API usage
- Deploy as an app
Step 3: Write Some Code!
Here's the fun part. I believe in separating classes/files into what makes sense in my mind.
Let's start by creating a Constants
class to define all of our constant variables:
# main.py
class Constants:
ATL_AIRPORT_ID = 5182
LOCATION_ID = ATL_AIRPORT_ID
SCHEDULER_API_ENDPOINT = 'https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=1&locationId={}&minimum=1'.format(
LOCATION_ID)
Doesn't the ATL_AIRPORT_ID
value look familiar? We're hardcoding Atlanta's location ID to use as a parameter later on.
The SCHEDULER_API_ENDPOINT
should look familiar as well. It is the same URL that we discovered in step 1. Notice I pass LOCATION_ID
here, which serves as my default
as more locations are added.
Create Bot
Compare two dates, A and B, where date A is the current scheduled appointment time. Notify twitter when the next available time slot (date B) is sooner than date A.
The Bot
should do at least two things:
- Check global entry schedule
- Notify me when a newer appointment is available
Let's start by creating a method to check the next available date for interview:
# main.py
import json
import datetime
import requests
class GlobalEntryBot(object):
def __init__(self):
pass
def check_global_entry_schedule(self):
"""
check date for global entry interview
:param interview_date: string format Y-m-d
:return:
"""
res = requests.get(Constants.SCHEDULER_API_ENDPOINT)
next_available_date_time = json.loads(res.text)[0]['startTimestamp'].split("T")
next_available_date = datetime.datetime.strptime(next_available_date_time[0], '%Y-%m-%d').date()
check_global_entry_schedule
will execute the GET
request
res = requests.get(Constants.SCHEDULER_API_ENDPOINT)
Parse out the date from startTimestamp
and then convert it to a datetime
object.
next_available_date = datetime.datetime.strptime(next_available_date_time[0], '%Y-%m-%d').date()
Now we have the next_available_date
for a Global Entry Interview in ATL_AIRPORT_ID
!
Take a look at Part 2 for some logic