{"info":{"_postman_id":"bfba53f7-0239-4f63-803b-c84f3cf1668d","name":"Air Quality","description":"<html><head></head><body><h1 id=\"postman-air-quality-collection\">Postman Air Quality Collection</h1>\n<p><strong>Welcome to the Postman Air Quality Collection.</strong><br>This collection was created in response to the 2017 wildfires that devastated Northern California. The fires brought tragedy, and also caused hazardous ash and smoke pollution in the surrounding areas. As Postman has an office in San Francisco, we thought it was important to help our fellow Northern Californians and the rest of the world stay aware of the air quality in their surroundings.</p>\n<p>This collection gets air quality updates from the AccuWeather API and posts them to Twitter according to your account and location specifications.</p>\n<h2 id=\"technologies-used\">Technologies Used</h2>\n<ol>\n<li><strong>Postman</strong> - This collection utilizes <a href=\"https://www.getpostman.com/docs/postman/collections/creating_collections\">Postman Collections</a>, <a href=\"https://www.getpostman.com/docs/postman/monitors/intro_monitors\">Postman Monitors</a>, and <a href=\"https://www.getpostman.com/docs/postman/environments_and_globals/manage_environments\">Postman Environments</a>.</li>\n<li><strong>AccuWeather API</strong> - <a href=\"https://developer.accuweather.com/home\">AccuWeather’s API</a> allows users to obtain real weather data, including air quality data.<ul>\n<li><strong>Using the AccuWeather API</strong> -<br>  To use AccuWeather’s API you will need to create an account and obtain a trial API key from their website. You can make up to 50 calls to the API per day on the trial, which should be enough to run this collection as an individual user.</li>\n</ul>\n</li>\n<li><strong>Twitter</strong> - We’ve chosen to use the <a href=\"https://developer.twitter.com/en/docs/basics/getting-started\">Twitter API</a> as a platform to reach out to our community and spread the message about the state of the San Francisco air quality since the Northern California fires have started. You can configure your own Twitter account to post periodic air quality updates.<ul>\n<li><strong>Using the Twitter API</strong> -<br>  To use Twitter’s API, you will need to create <a href=\"https://apps.twitter.com/\">a Twitter app</a> and get OAuth credentials.</li>\n</ul>\n</li>\n</ol>\n<h2 id=\"environment-variables\">Environment Variables</h2>\n<p>You need to set several environment variables before this collection will run:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Environment Variable Name</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>location</code></td>\n<td>A string describing the location you would like to monitor</td>\n</tr>\n<tr>\n<td><code>accuweatherApiKey</code></td>\n<td>An <a href=\"https://developer.accuweather.com/home\">AccuWeather API key</a></td>\n</tr>\n<tr>\n<td><code>twitterConsumerKey</code></td>\n<td><a href=\"https://developer.twitter.com/en/docs/basics/getting-started\">A Twitter OAuth Consumer Key</a></td>\n</tr>\n<tr>\n<td><code>twitterConsumerSecret</code></td>\n<td><a href=\"https://developer.twitter.com/en/docs/basics/getting-started\">A Twitter OAuth Consumer Secret</a></td>\n</tr>\n<tr>\n<td><code>twitterAccessToken</code></td>\n<td><a href=\"https://developer.twitter.com/en/docs/basics/getting-started\">A Twitter OAuth Access Token</a></td>\n</tr>\n<tr>\n<td><code>twitterAccessSecret</code></td>\n<td><a href=\"https://developer.twitter.com/en/docs/basics/getting-started\">A Twitter OAuth Access Token Secret</a></td>\n</tr>\n</tbody>\n</table>\n</div></body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[{"content":"Postman Air Quality Collection","slug":"postman-air-quality-collection"}],"owner":"10582367","collectionId":"bfba53f7-0239-4f63-803b-c84f3cf1668d","publishedId":"TVCY5rg9","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"EF5B25"},"publishDate":"2020-08-24T21:45:17.000Z"},"item":[{"name":"Get Air Quality Status","event":[{"listen":"prerequest","script":{"id":"cc8b5ffc-aeea-45db-b1e6-b72079203433","exec":["// Validate environment variables","const pmEnvironment = pm.environment.toObject();","","// Check for required environment variables","pm.expect(pmEnvironment).to.have.all.keys(","    'location',","    'accuweatherApiKey',","    'twitterConsumerKey',","    'twitterConsumerSecret',","    'twitterAccessToken',","    'twitterAccessTokenSecret'",");","","// Get an accuweather location key","const apiKey = pm.environment.get('accuweatherApiKey');","const locationQuery = pm.environment.get('location');","const getLocationData = `http://dataservice.accuweather.com/locations/v1/search?apikey=${apiKey}&q=${locationQuery}`;","","// Get and save location data from a location query string","function saveLocationData (e, response) {","    // Throw if we get an error","    if (e) { throw e; }","    ","    // Handle error response","    if (response.code >= 400) {","        console.log(`PROBLEM :: ${response.code} error while getting location.`);","        console.log(response.text());","        ","        // Throw","        throw new Error(`Couldn\\'t get location. Check your environment's location value.`);","    }","    ","    // Log location info and store the location information","    const responseData = response.json();","    ","    if (responseData.length > 1) {","        console.log('WARNING :: Query returned multiple results. Returning the first result.');","    }","    ","    const [{ Key: locationKey, EnglishName: locationName }] = responseData;","    ","    pm.globals.set('locationKey', locationKey);","    pm.globals.set('locationName', locationName);","    ","    console.log(`Getting air quality data for ${locationName} (AccuWeather key ${locationKey})`);","}","","// Send the request to get location data","pm.sendRequest(getLocationData, saveLocationData);"],"type":"text/javascript","packages":{}}},{"listen":"test","script":{"id":"5a308bf3-ea01-4bda-a8d8-7369358bf3ad","exec":["// Test the response","pm.test('Status code is OK', () => {","    pm.response.to.be.ok;","});","","pm.test('Response has forecast data', () => {","    pm.expect(pm.response.json()).to.have.property('DailyForecasts');","});","","try {","    // Check for a non-error response code","    if (pm.response.code >= 400) {","        console.log(`ERROR :: ${pm.response.code} response from API.`);","","        throw new Error('Error response from API.');","    }","","    // Extract the air quality data","    const responseData = pm.response.json();","    const airAndPollen = responseData.DailyForecasts[0].AirAndPollen;","    const airQuality = airAndPollen.find(value => value.Name === 'AirQuality');","    const aqValue = airQuality.Value;","    const aqCategory = airQuality.Category;","    const locationName = pm.globals.get('locationName');","    ","    // Build the Twitter status","    const twitterStatus =","        `The air quality index in ${locationName} is ${aqValue} (${aqCategory}).`;","    ","    // Log the Twitter status","    console.log(`Twitter status :: ${twitterStatus}`);","    ","    // Assign status to a Twitter global","    pm.globals.set('twitterStatus', twitterStatus);","}","catch (e) {","    // The data probably didn't match the expected values","    console.log(`ERROR :: ${e.message}`);","    console.log(pm.response.text());","","    throw e;","}",""],"type":"text/javascript","packages":{}}}],"id":"0da12f5b-4979-4e02-9e88-c17061286681","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"http://dataservice.accuweather.com/forecasts/v1/daily/1day/{{locationKey}}.json?apikey={{accuweatherApiKey}}&details=true","description":"<p>Get air quality data from the <a href=\"https://developer.accuweather.com/\">AccuWeather API</a>.</p>\n","urlObject":{"protocol":"http","path":["forecasts","v1","daily","1day","{{locationKey}}.json"],"host":["dataservice","accuweather","com"],"query":[{"key":"apikey","value":"{{accuweatherApiKey}}"},{"key":"details","value":"true"}],"variable":[]}},"response":[{"id":"52101d35-c492-46b3-a3f7-dcbbf6e293c8","name":"AccuWeather Forecast","originalRequest":{"method":"GET","header":[],"url":{"raw":"http://dataservice.accuweather.com/forecasts/v1/daily/1day/{{locationKey}}.json?apikey={{accuweatherApiKey}}&details=true","protocol":"http","host":["dataservice","accuweather","com"],"path":["forecasts","v1","daily","1day","{{locationKey}}.json"],"query":[{"key":"apikey","value":"{{accuweatherApiKey}}"},{"key":"details","value":"true"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Accept","value":"*/*","name":"Accept","description":""},{"key":"Access-Control-Allow-Headers","value":"origin, x-requested-with, accept","name":"Access-Control-Allow-Headers","description":""},{"key":"Access-Control-Allow-Methods","value":"GET, PUT, POST, DELETE","name":"Access-Control-Allow-Methods","description":""},{"key":"Access-Control-Allow-Origin","value":"*","name":"Access-Control-Allow-Origin","description":""},{"key":"Access-Control-Max-Age","value":"3628800","name":"Access-Control-Max-Age","description":""},{"key":"Cache-Control","value":"no-cache","name":"Cache-Control","description":""},{"key":"Connection","value":"keep-alive","name":"Connection","description":""},{"key":"Content-Encoding","value":"gzip","name":"Content-Encoding","description":""},{"key":"Content-Type","value":"application/json; charset=utf-8","name":"Content-Type","description":""},{"key":"Date","value":"Fri, 13 Oct 2017 19:58:03 GMT","name":"Date","description":""},{"key":"Expires","value":"Fri, 13 Oct 2017 20:18:02 GMT","name":"Expires","description":""},{"key":"Postman-Token","value":"a3a18946-c1dc-4080-a677-ec16d3d60999","name":"Postman-Token","description":""},{"key":"RateLimit-Limit","value":"50","name":"RateLimit-Limit","description":""},{"key":"RateLimit-Remaining","value":"31","name":"RateLimit-Remaining","description":""},{"key":"Server","value":"Microsoft-IIS/10.0","name":"Server","description":""},{"key":"User-Agent","value":"PostmanRuntime/6.4.0","name":"User-Agent","description":""},{"key":"Vary","value":"Accept-Encoding","name":"Vary","description":""},{"key":"X-Forwarded-For","value":"204.14.158.214","name":"X-Forwarded-For","description":""},{"key":"X-Forwarded-Port","value":"80","name":"X-Forwarded-Port","description":""},{"key":"X-Forwarded-Proto","value":"http","name":"X-Forwarded-Proto","description":""},{"key":"accept-encoding","value":"gzip","name":"accept-encoding","description":""},{"key":"accept-encoding","value":"deflate","name":"accept-encoding","description":""},{"key":"transfer-encoding","value":"chunked","name":"transfer-encoding","description":""}],"cookie":[],"responseTime":null,"body":"{\"Headline\":{\"EffectiveDate\":\"2017-10-13T08:00:00-07:00\",\"EffectiveEpochDate\":1507906800,\"Severity\":7,\"Text\":\"Smoky today to tomorrow\",\"Category\":\"smoke\",\"EndDate\":\"2017-10-14T20:00:00-07:00\",\"EndEpochDate\":1508036400,\"MobileLink\":\"http://m.accuweather.com/en/us/san-francisco-ca/94103/extended-weather-forecast/347629?lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?lang=en-us\"},\"DailyForecasts\":[{\"Date\":\"2017-10-13T07:00:00-07:00\",\"EpochDate\":1507903200,\"Sun\":{\"Rise\":\"2017-10-13T07:16:00-07:00\",\"EpochRise\":1507904160,\"Set\":\"2017-10-13T18:35:00-07:00\",\"EpochSet\":1507944900},\"Moon\":{\"Rise\":\"2017-10-13T00:53:00-07:00\",\"EpochRise\":1507881180,\"Set\":\"2017-10-13T15:17:00-07:00\",\"EpochSet\":1507933020,\"Phase\":\"WaningCrescent\",\"Age\":23},\"Temperature\":{\"Minimum\":{\"Value\":53.0,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":68.0,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperature\":{\"Minimum\":{\"Value\":50.0,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":74.0,\"Unit\":\"F\",\"UnitType\":18}},\"RealFeelTemperatureShade\":{\"Minimum\":{\"Value\":50.0,\"Unit\":\"F\",\"UnitType\":18},\"Maximum\":{\"Value\":65.0,\"Unit\":\"F\",\"UnitType\":18}},\"HoursOfSun\":12.1,\"DegreeDaySummary\":{\"Heating\":{\"Value\":4.0,\"Unit\":\"F\",\"UnitType\":18},\"Cooling\":{\"Value\":0.0,\"Unit\":\"F\",\"UnitType\":18}},\"AirAndPollen\":[{\"Name\":\"AirQuality\",\"Value\":158,\"Category\":\"Unhealthy\",\"CategoryValue\":4,\"Type\":\"Particle Pollution\"},{\"Name\":\"Grass\",\"Value\":2,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Mold\",\"Value\":0,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Ragweed\",\"Value\":5,\"Category\":\"Low\",\"CategoryValue\":1},{\"Name\":\"Tree\",\"Value\":50,\"Category\":\"Moderate\",\"CategoryValue\":2},{\"Name\":\"UVIndex\",\"Value\":12,\"Category\":\"Extreme\",\"CategoryValue\":5}],\"Day\":{\"Icon\":2,\"IconPhrase\":\"Mostly sunny\",\"ShortPhrase\":\"Hazy sunshine\",\"LongPhrase\":\"Smoky with hazy sunshine; breezy this afternoon\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":1,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":11.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":289,\"Localized\":\"WNW\",\"English\":\"WNW\"}},\"WindGust\":{\"Speed\":{\"Value\":26.5,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":299,\"Localized\":\"WNW\",\"English\":\"WNW\"}},\"TotalLiquid\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0.0,\"HoursOfRain\":0.0,\"HoursOfSnow\":0.0,\"HoursOfIce\":0.0,\"CloudCover\":21},\"Night\":{\"Icon\":33,\"IconPhrase\":\"Clear\",\"ShortPhrase\":\"Clear\",\"LongPhrase\":\"Clear\",\"PrecipitationProbability\":0,\"ThunderstormProbability\":1,\"RainProbability\":0,\"SnowProbability\":0,\"IceProbability\":0,\"Wind\":{\"Speed\":{\"Value\":5.8,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":314,\"Localized\":\"NW\",\"English\":\"NW\"}},\"WindGust\":{\"Speed\":{\"Value\":17.3,\"Unit\":\"mi/h\",\"UnitType\":9},\"Direction\":{\"Degrees\":300,\"Localized\":\"WNW\",\"English\":\"WNW\"}},\"TotalLiquid\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Rain\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Snow\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"Ice\":{\"Value\":0.0,\"Unit\":\"in\",\"UnitType\":1},\"HoursOfPrecipitation\":0.0,\"HoursOfRain\":0.0,\"HoursOfSnow\":0.0,\"HoursOfIce\":0.0,\"CloudCover\":0},\"Sources\":[\"AccuWeather\"],\"MobileLink\":\"http://m.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?day=1&lang=en-us\",\"Link\":\"http://www.accuweather.com/en/us/san-francisco-ca/94103/daily-weather-forecast/347629?day=1&lang=en-us\"}]}"}],"_postman_id":"0da12f5b-4979-4e02-9e88-c17061286681"},{"name":"Post Air Quality Status to Twitter","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["",""],"id":"8d2b675a-eb20-43d5-99c7-e44a39df8ccc"}},{"listen":"test","script":{"type":"text/javascript","exec":["// Check for OK response","pm.test('Status code is OK', () => {","    pm.response.to.be.ok;","});","","// Clear global state","pm.globals.clear('locationKey');","pm.globals.clear('locationName');","pm.globals.clear('twitterStatus');"],"id":"409f1d9a-85de-4652-99b3-382a56a438b8"}}],"id":"ca39bd7b-7a2e-4765-a694-f7edfd1c72d8","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"oauth1","oauth1":{"basicConfig":[{"key":"consumerKey","value":"{{twitterConsumerKey}}"},{"key":"consumerSecret","value":"{{twitterConsumerSecret}}"},{"key":"token","value":"{{twitterAccessToken}}"},{"key":"tokenSecret","value":"{{twitterAccessTokenSecret}}"}],"advancedConfig":[{"key":"signatureMethod","value":"<signature-method>"},{"key":"timestamp","value":"<timestamp>"},{"key":"nonce","value":"<nonce>"},{"key":"version","value":"<version>"},{"key":"realm","value":"<realm>"}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"formdata","formdata":[]},"url":"https://api.twitter.com/1.1/statuses/update.json?status={{twitterStatus}}","urlObject":{"protocol":"https","path":["1.1","statuses","update.json"],"host":["api","twitter","com"],"query":[{"key":"status","value":"{{twitterStatus}}"}],"variable":[]}},"response":[],"_postman_id":"ca39bd7b-7a2e-4765-a694-f7edfd1c72d8"}]}