Reputation: 399
I've been tasked with writing a program which interacts with the API for ClearBooks. They have some documentation but I'm still really struggling to get started. From what I can gather from the documentation, in order to receive the seemingly mythical "response 200", I need to:
My current code is as follows:
import requests
url = "https://secure.clearbooks.co.uk/api/soap/"
headers = {"Content-Type": "text/xml", "apiKey": "(api key goes here)"}
response = requests.get(url=url, headers=headers)
print(response)
print(response.text)
>>> <Response [500]>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>Sender</faultcode><faultstring>Invalid XML</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
I'm aware that my code probably looks really stupid, however this is the first time I've tried to write a program that interacts with the internet, and despite having spent a few days trying to hack it, it's something I'm finding really difficult - I've managed to scrape text from generic webpages but haven't managed to interact with any APIs without Codecademy or similar. Please could someone update my code (or more likely go from scratch) so that it works? I realise it's not something you can test without your own Clearbooks API key, but any help would be very greatly appreciated.
Upvotes: 1
Views: 1000
Reputation: 33823
Your code is not stupid at all.
But currently you are making an HTTP 'GET' request. This is the same as typing a url into your web browser and hitting enter.
Your first instruction though is to "post an XML request" to the SOAP server url. When you make a 'POST' request it's like when you submit a form on a web page. In other words you don't just request a url, you send some data to that url as well.
In this case you need to prepare a valid SOAP message, which is an XML document, and POST that to the SOAP server url.
See here: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests
In this case we are not posting form-encoded data, we want to send the XML as a string (see second example at url above)
It's entirely possible to do this manually, by typing in the correct message as a string. But it's probably easier to at least use an XML lib such as lxml
or a dedicated SOAP library such as suds
to make this easier.
One thing I would point out is that a "SOAP Header" is part of the XML message and not the same as an HTTP header. http://www.w3schools.com/webservices/ws_soap_header.asp
You have correctly sent the Content-Type: text/xml
HTTP header though, well done :)
Upvotes: 2
Reputation: 399
import requests
url = "https://secure.clearbooks.co.uk/api/soap/"
header = {"Content-Type": "text/xml"}
myxml = """<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
xmlns:cb="https://secure.clearbooks.co.uk/api/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Header>
<cb:authenticate apiKey="API_key_goes_here" />
</env:Header>
<env:Body>
<env:listProjects env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
offset="3"
</env:listProjects>
</env:Body>
</env:Envelope>
"""
response = requests.post(url, data=myxml, headers=header)
print(response)
>>> <Response [200]>
Upvotes: 2