This blog post was written for Twilio and originally published on the Twilio blog.
Congress recently came out with an official API so the public can "view, retrieve, and re-use machine-readable data from collections available on Congress.gov!" Read on to learn how to read congressional data using the Congress API, Twilio Functions, and the Twilio Serverless Toolkit.
Text "bill", "amendment", or "summaries" to +12029337044 to receive data about a random bill or amendment!
Prerequisites
- A Twilio account - sign up for a free one here
- A Twilio phone number with SMS capabilities - configure one here
- A Congress.gov API Key – get one here
- Postman (you could alternatively make cURL requests from the command line)
- Node.js installed - download it here
Make a congress.gov Request
You can look over the different Congress API endpoints offered here. To get someone's profile information, the URL would look like [https://api.congress.gov/v3/bill/117/s/4693/summaries](https://api.congress.gov/v3/bill/117/s/4693/summaries)
where 117 is the [Congress numberhttps://en.wikipedia.org/wiki/117th_United_States_Congress, "s" is the type of bill, and "4693" is the bill number. Open Postman and paste that URL into the URL bar.
Add your API Key under Params: the key
is api_key
and the value
is your Congress API Key.
Click Send
to hit it with a GET request to see the following data returned:
Again, you can see more Congress API endpoints here you can play around with!
Get Started with the Twilio Serverless Toolkit
The Serverless Toolkit is CLI tooling that helps you develop locally and deploy to Twilio Functions & Assets. The best way to work with the Serverless Toolkit is through the Twilio CLI. If you don't have the Twilio CLI installed yet, run the following commands on the command line to install it and the Serverless Toolkit:
npm install twilio-cli -g
twilio login
twilio plugins:install @twilio-labs/plugin-serverless
Afterwards, create your new project and install our lone requirement [undici](https://github.com/nodejs/undici)
to make HTTP requests in Node.js by running:
twilio serverless:init congress-api-sms –template=blank
cd congress-api-sms
npm install -s undici
The Functions and Assets team recommends using undici
with your Functions.
Set an Environment Variable with Twilio Functions and Assets
Open up your .env
file for your Functions project in your root directory and add the following line:
CONGRESS_API_KEY=YOUR-CONGRESS-API-KEY
Now you can access this API Key if you'd like to do so in your code with context.CONGRESS_API_KEY
.
Make a Twilio Function with JavaScript
Make a new file in the /functions
directory called congress.js containing the following code:
exports.handler = async (context, event, callback) => {
const { request } = await import('undici');
const inbMsg = event.Body.toLowerCase().trim();
const twiml = new Twilio.twiml.MessagingResponse();
if(inbMsg.includes("bill")) {
const {
body
} = await request(`https://api.congress.gov/v3/bill?api_key=${context.CONGRESS_API_KEY}`);
const data = await body.json();
const billsLength = data.bills.length;
const randNum = Math.floor(Math.random() * (billsLength - 1)) + 1;
const bill = data.bills[randNum];
const { latestAction, title, type, number, originChamber } = bill;
const billMap = {
HR: "house bill",
S: "senate bill",
HJRES: "house joint resolution",
SJRES: "senate joint resolution",
HCONRES: "house concurrent resolution",
SCONRES: "senate concurrent resolution",
HRES: "house simple resolution",
SRES: "senate simple resolution"
};
twiml.message(`Bill: ${title}.\nType: ${billMap[type]}\nAssigned bill or resolution number: ${number}\nIt originated in the ${originChamber} but the latest action was ${latestAction.text} on ${latestAction.actionDate}`);
}
else if(inbMsg.includes("amendment")) {
const {
body
} = await request(`https://api.congress.gov/v3/amendment?api_key=${context.CONGRESS_API_KEY}`);
const data = await body.json();
const amendmentLength = data.amendments.length;
const randNum = Math.floor(Math.random() * (amendmentLength - 1)) + 1;
const amendment = data.amendments[randNum];
const { latestAction, purpose, congress, number } = amendment;
twiml.message(`Amendment purpose: ${purpose}\nAssigned amendment or resolution number:${number}\n Latest action was on ${latestAction.actionDate} to ${latestAction.text}.\n Congress: ${congress}.`);
}
else if(inbMsg.includes("summaries")) {
const CURRENT_CONGRESS = 117;
const {
body
} = await request(`https://api.congress.gov/v3/summaries/${CURRENT_CONGRESS}?api_key=${context.CONGRESS_API_KEY}`);
const data = await body.json();
const sumLength = data.summaries.length;
const randNum = Math.floor(Math.random() * (sumLength - 1)) + 1;
const summaries = data.summaries[randNum];
const { bill, currentChamber, text, actionDate, actionDesc } = summaries;
const regexToStripHtmlTags = /<(.|\n)*?>/g;
const textWithoutHtmlTags = text.replace(regexToStripHtmlTags, '');
const msg = `Summary title: ${bill.title}.\nStarted in: ${bill.originChamber} on ${actionDate}, currently in the ${currentChamber} chamber in Congress ${bill.congress} and it was ${actionDesc}\n${textWithoutHtmlTags}`;
twiml.message(msg);
}
else {
twiml.message(`Send "bill", "amendment", or "summaries"`);
}
callback(null, twiml);
};
This code imports undici
, makes a Twilio Messaging Response object, creates a variable inbMsg
from the inbound text message users will text in and checks if that message input contains bill
, amendment
, or summaries
(three endpoints of the Congress API). The code then generates a random number based on the total amount of items returned from the Congress API to select a random Bill or Amendment, parses the responses from that given endpoint (as we saw using Postman above) into variables such as the type of Amendment or Bill, the most recent date some action was taken, and more!
If someone does not send a message containing "bill", "summaries", or "amendment" (the three topics they can learn about), we return a message saying so. Else, we parse the Congress object returned for information such as the latest action taken on a bill, type of bill, purpose of the given random amendment, origin chamber of a bill, and more. We return a text message containing that data!
You can view the complete app on GitHub here.
Configure the Function with a Twilio Phone Number
To open up our app to the web with a public-facing URL, run twilio serverless:deploy
from the congress-api-sms
root directory. You should see this at the bottom of your terminal:
Grab the Function URL corresponding to your app (the one that ends with /congress
) and configure a Twilio phone number with it as shown below: select the Twilio number you just purchased in your Twilio phone numbers console and scroll down to the Messaging section. Paste the link in the text field for A MESSAGE COMES IN webhook making sure that it's set to HTTP POST. When you click Save it should look like this!
The Service is the Serverless project name, environment provides no other options, and Function Path is the file name. Now take out your phone and text "bill" or "amendment" or "summaries" to your Twilio number.
What's Next for Twilio Serverless and the Congress API?
Twilio's Serverless Toolkit makes it possible to deploy web apps quickly, and Functions & Assets seamlessly handles servers for you. You can do a lot with this data, and you can see what actions Congress are taking--it's fun data to play around with! Let me know online what you're building with Twilio Functions&Assets and don't forget to vote this November!