Life is easier in XML
Are you ready for this conversation?
A couple of months back, I’ve joined a team that handles integrations with the Brazilian Central Bank(Bacen) for the Pix transactions system.
The first thing that was said to me was: “Everything is based on XML”. And my first instinct was to make an ugly face. XML? Why?
I have never worked in a financial institution before, and after this, I discover that all the communication between financial institutions is based upon XML. There’s the ISO 20022 that regulates and standardizes the format of the XML’s and its purposes.
If you never heard about the Brazilian Pix, is a technology developed by the Central Bank that allows anyone to transfer money in seconds 24/7.
Based on its latest data, we have around more than ~5 million transfers per month in the last 6 months of the service.
And where the XML enters in the Pix journey? In every scenario of a Pix transaction, it’s represented by a specific message. Lately I was coding the messages related to the Automatic Pix flow, where we have a set of messages responsible to handler recurring payments through Pix.
So, consider the CAMT.055 message. This message is responsible for the cancellation of a recurring payment. Let’s see, it’s XML:
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| <Envelope xmlns="https://www.bcb.gov.br/pi/camt.055/1.0"> | |
| <AppHdr> | |
| <Fr> | |
| <FIId> | |
| <FinInstnId> | |
| <Othr> | |
| <Id>00038166</Id> | |
| </Othr> | |
| </FinInstnId> | |
| </FIId> | |
| </Fr> | |
| <To> | |
| <FIId> | |
| <FinInstnId> | |
| <Othr> | |
| <Id>22222222</Id> | |
| </Othr> | |
| </FinInstnId> | |
| </FIId> | |
| </To> | |
| <BizMsgIdr>M0003816612345678901234567890123</BizMsgIdr> | |
| <MsgDefIdr>camt.055.spi.1.0</MsgDefIdr> | |
| <CreDt>2024-01-01T08:30:12.000Z</CreDt> | |
| <Sgntr/> | |
| </AppHdr> | |
| <Document> | |
| <CstmrPmtCxlReq> | |
| <Assgnmt> | |
| <Id>M0003816612345678901234567890123</Id> | |
| <Assgnr> | |
| <Agt> | |
| <FinInstnId> | |
| <ClrSysMmbId> | |
| <MmbId>11111111</MmbId> | |
| </ClrSysMmbId> | |
| </FinInstnId> | |
| </Agt> | |
| </Assgnr> | |
| <Assgne> | |
| <Agt> | |
| <FinInstnId> | |
| <ClrSysMmbId> | |
| <MmbId>22222222</MmbId> | |
| </ClrSysMmbId> | |
| </FinInstnId> | |
| </Agt> | |
| </Assgne> | |
| <CreDtTm>2024-01-01T08:30:12.000Z</CreDtTm> | |
| </Assgnmt> | |
| <Undrlyg> | |
| <OrgnlPmtInfAndCxl> | |
| <PmtCxlId>CA1111111120240101qwertyuiopa</PmtCxlId> | |
| <OrgnlPmtInfId>1aws29eicn7shdyr4judifkws8</OrgnlPmtInfId> | |
| <CxlRsnInf> | |
| <Orgtr> | |
| <Id> | |
| <PrvtId> | |
| <Othr> | |
| <Id>12345678900</Id> | |
| </Othr> | |
| </PrvtId> | |
| </Id> | |
| </Orgtr> | |
| <Rsn> | |
| <Prtry>SLBD</Prtry> | |
| </Rsn> | |
| </CxlRsnInf> | |
| <TxInf> | |
| <OrgnlEndToEndId>E22222222202401081500qwertyuiopp</OrgnlEndToEndId> | |
| <SplmtryData> | |
| <Envlp> | |
| <CxlPrcgDtls> | |
| <CxlPrcgTp>DHIP</CxlPrcgTp> | |
| <PrcgDtTm>2024-01-01T08:30:11.000Z</PrcgDtTm> | |
| </CxlPrcgDtls> | |
| </Envlp> | |
| </SplmtryData> | |
| </TxInf> | |
| </OrgnlPmtInfAndCxl> | |
| </Undrlyg> | |
| </CstmrPmtCxlReq> | |
| </Document> | |
| </Envelope> |
As you can see, it’s pretty verbose, and I do think that these XML’s could be simplified, however, since they are based in the international standards of the ISO, there’s not much room for improvements.
We send and receives the XML messages through streams between our institution infrastructure and the Central Bank. And there’s a lot of them. Just on the Automatic Pix journey there’s around 7-10 messages. And we need to implement the parser to create and receive these messages.
So far, you might still think that a REST API would be better than this XML soup, however, the dealbreaker for me is a file called camt055.xsd.
Every tag in the XML has a structure, and each of them has rules that need to be respected for the data passed in each tag.
You might be asking what is the XSD file… XSD stands for XML Schema Definition, and it’s the blueprints with the rules that define the XML structure and data validation. For the CAMT.055 you can check it’s XSD here.
You can see on the link how the structure it’s defined, and the tag types with its validation. Here we have an example on how the type ISPBType is defined, as you can see, we have a max length of the type and a regex that validate its pattern.
That, for me, is pure gold. We are dealing with a very sensitive workflow that handles people’s money, and it’s a system that has small room for error. If we used a REST API, how many times should I deal with a Bad Request until I properly formatted the data for the Pix API? With the XSD, I can guarantee on my unit tests that the XML created from my institution data is properly formatted and validated. I could expand the use of the XSD validation before sending the message to Bacen, but so far, having this assurance in the unit tests, gives us some peace of mind.
I’m using the go-xsd-validate for the validation of the XML in the unit tests. It’s quick setup library allows you for a quick feedback.
And since the XSD also offer the rules (mostly regex) for each tag, I can extract these rules to my app and create validations for the fields, before creating the XML. And then using the XSD validation on the tests, we can cover all bases, and make sure that the data is correct moving forward.
And with this, I lost my pre-conception of XML being a bad way for API communication, at least for the financial world. =)
That’s all for today, folks!


