DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Pull Congressional Data via SMS with the Congress API and JavaScript
Lizzie Siegle for Twilio

Posted on

Pull Congressional Data via SMS with the Congress API and JavaScript

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!
sms example

Prerequisites

  1. A Twilio account - sign up for a free one here
  2. A Twilio phone number with SMS capabilities - configure one here
  3. A Congress.gov API Key – get one here
  4. Postman (you could alternatively make cURL requests from the command line)
  5. 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:
congress API data returned in Postman
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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
};
Enter fullscreen mode Exit fullscreen mode

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:
twilio function urls once deployed
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!
messaging section of twilio phone number
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.
sms example

What's Next for Twilio Serverless and the Congress API?

being in congress must be fun kimmy schmidt gif
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!

Top comments (0)

Timeless DEV post...

How to write a kickass README

Arguably the single most important piece of documentation for any open source project is the README. A good README not only informs people what the project does and who it is for but also how they use and contribute to it.

If you write a README without sufficient explanation of what your project does or how people can use it then it pretty much defeats the purpose of being open source as other developers are less likely to engage with or contribute towards it.