<jupyter_start><jupyter_text>The NHSX Analytics Unit introduction to Python Session 3---This article was very useful and recommended - https://realpython.com/python-api/ Application Programming Interface (APIs) allow different systems to exchange (send or recieve) data. This could be used to automatically update a record/database or to send a data extract.Currently, APIs are mostly used in software/app development to pass data and messages smoothly.  They also allow granular access to many large databases for analytical exploration.  However, in my experience these are often databases that are well managed and accessible already so often the API work loses potency from actual application after training.   This shouldn't deter us as API usage and being a standard way of accessing data is on the rise across government and in the NHS.  In paricular, NHSX should be leading on the call for more accessible data through APIs and so understanding how to build and use these is important.   Example well-known APIsAPIs are all around us but often hidden away doing the legwork to make smooth data flows e.g. weather apps on your phone, paypal, and loggin through google all use APIs.![Commonly used APIs](https://github.com/nhs-pycom/coding-club-apis/blob/main/images/commonUses.png?raw=1)Take a look at:- https://any-api.com/- https://github.com/public-apis/public-apis (note: US focussed)**Top 50 most used APIs** *(accoriding to rapidaPIs.com in April 2021)*Many of these enable websites and apps to quickly updated to latest information based on a search criteria or location (excet 13)1. Skyscanner Flight Search2. Open Weather Map3. API-FOOTBALL4. The Cocktail DB5. REST Countries v16. Yahoo Finance7. Love Calculator8. URL Shortener Service9. NasaAPI10. Numbers11. musiXmatch12. SYSTRAN.io – Translation and NLP13. Chuck Norris14. Hearthstone15. Currency Exchange16. Breaking News17. Booking18. Free NBA19. Deezer20. Email Validator21. Urban Dictionary22. Pokemon Go23. Recipe – Food – Nutrition24. Investors Exchange (IEX) Trading25. Movie Database (IMDB Alternative)** Healthcare APIs **The lists I found on whilst searching github and google are mainly US based.  NHS Digitial has a range of APIs available listed here: https://digital.nhs.uk/developer/api-catalogue.  Many of these are to do with passing secure records between services and the security around these.    Types of API There are four common;y used API types:- Open/External/Public: Can be either completely open or require an API key- Internal: Hidden from external uses- Partner: Similar to Open APIs but use a third-party API gateway to manage access- Composite: Access to several end points at once (useful for dev)There are three standat sets of rules (Protocls) commonly used:- REST- RPC- SOAP- GraphQL (created by facebook)See here for more info: https://apifriends.com/api-creation/different-types-apis/ & https://www.altexsoft.com/blog/soap-vs-rest-vs-graphql-vs-rpc/Today we will focus on REST APIs  REST API - Terminology![Terminology](https://github.com/nhs-pycom/coding-club-apis/blob/main/images/terminology.png?raw=1)The API itself defines accessible endpoints and valid request and response formats  REST API Commands- POST - Create- GET - Read- PUT - Update- DELETE - DELETE*note: There are others not covered here*  Benefits of APIs- Security for underlying database- Consistency of output- Separate frontend fram backend allows for interoperability- Development without disruption or releaseshttps://www.england.nhs.uk/publication/open-api-architecture-policy/ Side note on http vs httpsWhilst most endpoints are https some are still http.  Note that https is the encrypted version for http communication.  Never send any sensitive or work data over a http connection.  JSON formatThe response most commonly comes in java script object notation (JSON).  This is a hierarchical list of key-value pairs similar to a Python dictionary.<jupyter_code>#Example JSON layout
 
# {
#     "firstName": "Duke",
#     "lastnName": "Java",
#     "age": 18,
#     "streetAddress": "100 Internet Dr",
#     "city": :"JavaTown",
#     "state": "JA",
#     "postalCode": "12345",
#     "phoneNumbers": [
#         { "Mobile": "111-111-1111" },
#         {"Home": "222-222-2222" }
#     ]
# }<jupyter_output><empty_output><jupyter_text>- An set of key-value pairs is called an object.- Within an object one key can have an array of sub key-values pairs.    - {} enclose objects    - , separate pairs within an object     - : separating keys and values    - [] enclose arrays- Objects can contain arrays which in turn can contain further objects or arrays and so on.  This means that we can end up with fairly complex tree structures.   PracticalSteps: - Choose the API to work with- Read the API documentation (this takes the most time)- Start with small code, and complement it with more features.Python has a few libraries used for interacting with APIs such as requests, pycurl, urllib and postman.   I find requests to be the easiest to start with however postman is good for testing estahblish APIs and good to read up on. Using the Python request package the code required is minimal (especially compared to other languages such as java).  We will also beed to import json and pprint to view the responses in a readable format.<jupyter_code>import requests
import json
import pprint<jupyter_output><empty_output><jupyter_text>Task 1: Find the ISS and who is currently in it*from https://medium.com/quick-code/absolute-beginners-guide-to-slaying-apis-using-python-7b380dc82236*<jupyter_code>request = requests.get('http://api.open-notify.org/iss-now.json')
print(request.status_code)<jupyter_output><empty_output><jupyter_text>If a request returns a status code 200 then everything is OK, if it returns 404 then the page or resource was not found.**Status code**- 200 "OK"	Your request was successful!- 201 "Created"	Your request was accepted and the resource was created.- 400 "Bad Request"	Your request is either wrong or missing some information.- 401 "Unauthorized"	Your request requires some additional permissions.- 404 "Not Found"	The requested resource does not exist.- 405 "Method Not Allowed"	The endpoint does not allow for that specific HTTP method.- 500 "Internal Server Error"	Your request wasn’t expected and probably broke something on the server side.To see the content which has been returned:<jupyter_code>print(request.text)
print(request.json())<jupyter_output><empty_output><jupyter_text>To get the latitude and longitude only we can filter by "iss_position<jupyter_code>print(request.json()['iss_position'])<jupyter_output><empty_output><jupyter_text>If we wanted we could now combine this with a geocoding API to give a map view.  I haven't done this here as it requires an API key but this is publicaly available if you want a go as a learning exercise. For the moment take a look at the documentation here: http://open-notify.org/Open-Notify-API/People-In-Space/ and spend **5-10 mins** trying to work out who is on the ISS right now.<jupyter_code>#CODE IN HERE<jupyter_output><empty_output><jupyter_text>NASA has some great APIs for instance one which allows the astronomoy picture of the day or Mars rover public images to be requested.  Again these need a free sign-in to get a key before use - https://api.nasa.gov/  Task 2: Search Stackoverflow QuestionsLets try a slightly more complicated request now.  This time we will use the API provided by stackoverflow to find relevent questionsThe API documentation can be found here: https://api.stackexchange.com/docsThis time when making the request we want the response to be sorted to our preference and perhaps with specific search criteria.  This can be done through the url in order to reduce the amount of data being requested.  The format for this is the same as for any url search that you may see (for instance when using a google search or scanning through a clickbait article)<jupyter_code>url = 'http://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=stackoverflow'
response = requests.get(url)
print(response.status_code)<jupyter_output><empty_output><jupyter_text>IT can be useful at times to see the headers of an API request or response.  The headers define a few parameters for what's accepted by the API.  Here we see that the server will only respond to json content, some details around content length and encoding, and lots of other bits and bobs.<jupyter_code>print(response.headers)<jupyter_output><empty_output><jupyter_text>A better way to set up the request is to separate the parameters from the URL so they can be easily changed by a user (e.g. through a GUI)<jupyter_code>url2 = 'http://api.stackexchange.com/2.2/questions'

parameters = {
    'order':'desc',
    'sort':'activity',
    'site':'stackoverflow',
}

response = requests.get(url2, params=parameters)
print(response.status_code)<jupyter_output><empty_output><jupyter_text>This should be the same result which you can check if you want!We now want to print out the response and find questions of interest.<jupyter_code>print(response.json()['items'])<jupyter_output><empty_output><jupyter_text>The full JSON requested has been printed.  A nicer way of printing this is to use **pprint**<jupyter_code>pprint.pprint(response.json())<jupyter_output><empty_output><jupyter_text>You may have expected more questions to be returned than you'll see here.  The limited number is due to paging.  For stack exchange page starts at and defaults to 1, pagesize can be any value between 0 and 100 and defaults to 30.  There is a section in the stack exchange documentation on paging and how to return total results, but as the reason for paging is not to overload the API, and we dont really need all the results, we'll stick with the defaults.APIs will also limit the rate if requests or "throttle" the number of request per second to avoid abuse or overloading.Use a for loop to run through the items and print only those meeting a certain condition<jupyter_code>term = [" r "," R ", "python", "Python"]

for data in response.json()['items']:
  if any(x in data['title'] for x in term):
    print(data['title'])
    print(data['link'])
    print()<jupyter_output><empty_output><jupyter_text>Now try and spend **5-10 mins** attempting to get find the "answer with the most votes along with the original question"<jupyter_code># CODE IN HERE<jupyter_output><empty_output><jupyter_text>If the Stack overflow example was a bit vanilla for you then have a look at https://thedogapi.com/ or https://thecatapi.com/ which I hear are really good examples of well documented APIs.  They do require a sign-up though so I've not touched them here for time.  Task 3: "Post" an updateExtracting data will be the most common use for data users.  However, it may be useful to also see posting data to a database.For this we need a server to post to.  I'll use requestbin hosted by pipedream for this.  Specifcially, https://requestbin.com/r/encygohnki5lb (note: this probably won't be available after the initial session but it's easy to genereate your own).  Documentation: https://requestbin.com/docs/examining-requests<jupyter_code>url_pipedream = "https://encygohnki5lb.x.pipedream.net/training/AU/"
mydict = {
    'fav_film': 'Lethal Weapon',
    'fav_scene': 'Woods',
          }<jupyter_output><empty_output><jupyter_text>Post your data to the requestbin<jupyter_code>requests.post(url_pipedream, data = mydict)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07448659937347721, 'fraction_numerical': 0.012443438914027148, 'mean_word_length': 4.729312063808575, 'pattern_counts': {'":': 10, '<': 61, '<?xml version=': 0, '>': 61, 'https://': 17, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '61161', 'license': 'MIT', 'n_tokens_mistral': 3301, 'n_tokens_neox': 3079, 'n_words': 1464, 'path': 'coding_club_apis.ipynb', 'repo_name': 'nhs-pycom/coding-club-apis', 'size': '11492'}