What Is SOAP? β Definition and How It Works
Learn what a SOAP API is, how the envelope and WSDL work, and how to call one when you encounter it.
SOAP is a protocol for exchanging structured messages as XML envelopes, usually over HTTP. It is contract-first: a WSDL document describes the operations, types, and endpoint before any code is written.
1. The Envelope
Every SOAP message has the same shape:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<auth:Credentials xmlns:auth="http://example.com/auth">
<auth:Token>...</auth:Token>
</auth:Credentials>
</soap:Header>
<soap:Body>
<GetProduct xmlns="http://example.com/catalog">
<ProductId>42</ProductId>
</GetProduct>
</soap:Body>
</soap:Envelope>
The header carries metadata such as authentication; the body carries the operation. Namespaces are mandatory and exact β a namespace mismatch is the single most common reason a hand-built SOAP request is rejected.
2. WSDL Is the Contract
A WSDL document is machine-readable and complete: operations, input and output types, faults, bindings, and the endpoint address.
That completeness is SOAP's real strength. Point a client generator at a WSDL and you get typed methods, no guesswork about field names, and validation before the request leaves.
from zeep import Client
client = Client("https://example.com/catalog?wsdl")
result = client.service.GetProduct(ProductId=42)
print(result.Name, result.Price)
3. Faults Instead of Status Codes
SOAP errors arrive as a fault inside the envelope, and typically with HTTP 500:
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Invalid ProductId</faultstring>
</soap:Fault>
This is the trap for anyone treating a SOAP endpoint as a plain HTTP service: a 500 may be an ordinary validation error, and retrying it is pointless. The status code carries almost no information β the fault does.
4. SOAPAction
Many services require a header naming the operation:
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://example.com/catalog/GetProduct"
Omitting it, or sending it without the quotes, produces an unhelpful error on a substantial number of implementations. A generated client handles this; a hand-built request often does not.
5. Where You Still Meet It
- Enterprise systems β ERP, CRM, and financial platforms with long lifecycles.
- Government and healthcare services, where standards were fixed years ago.
- Banking and payments, particularly where WS-Security is required.
- Telecoms provisioning and logistics carriers.
- Legacy internal services that were never migrated.
These are the contexts where a data source turns out to be SOAP rather than REST, which is why the format is worth knowing rather than merely worth avoiding.
6. Practical Advice
- Use a generated client.
zeepfor Python, JAX-WS for Java,gowsdlfor Go. Hand-built XML is a slow way to rediscover namespace rules. - Fetch and pin the WSDL locally. Live WSDL retrieval on every start is fragile and slow.
- Read faults, not statuses. Parse the fault code and string, and use them to decide retryability.
- Check whether a REST alternative exists. Many vendors now offer both, with the REST version documented and the SOAP version merely maintained.
- Expect verbosity. Envelopes are large; compression helps substantially.
- Watch dates and decimals. XML Schema types are precise, and a naive parse can silently change a decimal's precision.
7. Summary
SOAP is an XML envelope protocol with a machine-readable WSDL contract, mandatory namespaces, a SOAPAction header, and errors returned as faults rather than status codes.
It persists in enterprise, government, healthcare, and financial systems, so the practical approach is a generated client from a pinned WSDL, and error handling that reads the fault rather than the HTTP 500 wrapping it.