Search code examples
pythonresthl7-fhirhapi-fhir

Using Python Requests to POST data to REST API


I have been working with the FHIR REST API for a while but haven't had any experience with Python. As my first python project I am attempting to create a simple python script that can read and write to an open API. I am able to read but I am stuck on creating a successful POST due to the following: error [TypeError("unhashable type: 'dict'")]. I don't fully understand how the python dictionary works and attempted to use a tuple but get the same error.

import requests #REST Access to FHIR Server
print('Search patient by MRN to find existing appointment')
MRN = input("Enter patient's MRN -try CT12181 :")
url = 'http://hapi.fhir.org/baseR4/Patient?identifier='+MRN
print('Searching for Patient by MRN...@'+url)

response = requests.get(url)
json_response = response.json()

try:
  key='entry'
  EntryArray=json_response[key]
  FirstEntry=EntryArray[0]
  key='resource'
  resource=FirstEntry['resource']
  id=resource['id']
  PatientServerId= id
  patientName = resource['name'][0]['given'][0] + ' ' +resource['name'][0]['family']
  print('Patient Found')
  print('Patient Id:'+id)
  
  #Searching for assertppointments
  
  url='http://hapi.fhir.org/baseR4/Appointment?patient='+id #fhir server endpoint

  #Print appointment data 

  print('Now Searching for Appointments...@'+url)
  appt_response = requests.get(url).json()
  key='entry'
  EntryArray=appt_response[key]
  print (f'Appointment(s) found for the patient {patientName}')
  for entry in EntryArray:
    appt=entry['resource']
 #   print('-------------------------')
 #   Date=appt['start']
 #   Status=appt['status'] 
 #   print(appt_response)
   #print ('AppointmentStartDate/Time: ' ,appt['start'])
    print ('Status: ' ,appt['status'])
    print ('ID: ' ,appt['id'])

    
  print('Search for open general practice slot?')
  option = input('Enter yes or no: ')
  while not(option == 'yes'):
      print('Please search a different paitent')
      option = input('Enter yes or no: ')    
  url = 'http://hapi.fhir.org/baseR4/Slot?service-type=57' #fhir server endpoint
  print('Searching for General Practice Slot...@'+url)
  slot_response = requests.get(url).json()
  key='entry'
  EntryArray=slot_response[key]
  print ('Slot(s) found for the service type General Practice')
  for entry in EntryArray:
    slot=entry['resource']
    #print('-------------------------')
    #slotDate=slot['start']
    #slotStatus=slot['status'] 
    print (f'SlotID: ' +slot['id'])
    #print (f'Status: ' +slot['status'])    
  print('Book a slot?')
  option = input('Enter yes or no: ')
  while not(option == 'yes'):
      print('Please search a different paitent')
      option = input('Enter yes or no: ')
#Book slot  
  slotID = input("Enter slot ID :")
  url = 'http://hapi.fhir.org/baseR4/Appointment' #fhir server endpoint
  print('Booking slot...@'+url)
  headers = {"Content-Type": "application/fhir+json;charset=utf-8"}
  data = {{"resourceType": "Appointment","status": "booked","slot": tuple({"reference":"Slot/104602"}),"participant": tuple({"actor": {"reference":"Patient/1229151","status": "accepted"}}),"reasonCode": tuple({"text": "I have a cramp"})}}
#fhir server json header content
#  headers = {"Content-Type": "application/fhir+json;charset=utf-8"}
  response = requests.post(url=url,headers=headers,data=data)
  print(response)
  print(response.json())
except Exception as e:
    print ('error' ,[e])
  
   

I was expecting the JSON data to successfully write to the API. I am able to use the same JSON data in Postman to make a call, but I am not as familiar on how this should work within Python.


Solution

  • It looks like the Appointment POST endpoint accepts a simple payload like:

    {
      "resourceType": "Appointment"
    }
    

    Which then returns a corresponding ID, according to the API docs.

    This differs from what you seem to be attempting in your code, where you try to pass other details to this endpoint:

    ata = {{"resourceType": "Appointment","status": "booked","slot": tuple({"reference":"Slot/104602"}),"participant": tuple({"actor": {"reference":"Patient/1229151","status": "accepted"}}),"reasonCode": tuple({"text": "I have a cramp"})}}
    

    However, to make a POST request to the endpoint as documented in the docs, perhaps try the json argument to requests.post. Something along the lines of:

    >>> import requests
    >>> headers = {"Content-Type": "application/fhir+json;charset=utf-8"}
    >>> json_payload = {
    ...   "resourceType": "Appointment"
    ... }
    >>> url = 'http://hapi.fhir.org/baseR4/Appointment'
    >>> r = requests.post(url, headers=headers, json=json_payload)
    >>> r
    <Response [201]>
    >>> r.json()
    {'resourceType': 'Appointment', 'id': '2261980', 'meta': {'versionId': '1', 'lastUpdated': '2022-03-25T23:40:42.621+00:00'}}
    >>> 
    

    If you're already familiar with this API, then perhaps this might help. I suspect you then need to send another POST or PATCH request to another endpoint, using the ID returned in your first request to enter the relevant data.