Using Zeep to make SOAP requests in Python

Adrienne Domingus
3 min readMar 25, 2017

While most APIs are REST these days, there are still some SOAP ones out there — typically enterprise software or if you need the benefits of WS-security or the like. What brought me to SOAP was integrating with an enterprise payment gateway that had developed their own clients in several languages, but not Python, so I was on the hunt for my own. There are others, the short version of why I went with Zeep is because it was purported to be the most “modern” — we can argue about whether this was a good decision or rationale some other time. This is a pretty basic overview, but should enable you to make your first requests and clear up some hurdles I faced when some things were less clear than I would have liked in the docs.

Passing Parameters/Generating XML

One of the nice things about using Zeep is that you don’t actually need to write XML, which can be finicky. Create a dictionary with the relevant data, and it will create XML for you, based on an XML schema that you provide it (more on that later). For example, the following dictionary:

request_data = {
'merchantID': '1234abc',
'billTo': {
'street1': '400 Broad Street',
'city': 'Seattle',
'state': 'WA',
'postalCode': '98109',
'country': 'US',
},
'item': [{
'id': '0',
'unitPrice': '12.34',
'quantity': '1',
}],
'taxService': {
'run': "true",
'nexus': "WA, CA"
},
}

Results in the following XML:

<merchantID>1234abc</merchantID>
<billTo>
<street1>400 Broad Street</street1>
<city>Seattle</city>
<state>WA</state>
<postalCode>98109</postalCode>
<country>US</country>
</billTo>
<item id="0">
<unitPrice>12.34</unitPrice>
<quantity>1</unitPrice>
</item>
<taxService run="true">
<nexus>WA, CA</nexus>
</taxService>

It’s worth noting that parameters are passed into Zeep the same way fields are. The schema includes both attributes and fields, so they are applied correctly. Another thing to note is that boolean values should be passed in as lowercase strings, not as Python boolean values — Zeep doesn’t know to translate from an actual boolean.

Update: heard from a reader looking to include both an attribute and a field in the same element — i.e if I had wanted the tax_service element above to read <taxService run="true">WA, CA</taxService> instead. That can be accomplished by doing