Internal Format

The internally used data structure is almost identical to that of Peppol UBL Invoices. All supported output formats can be generated from it.

Why an Internal Format?

Data in the internal format is the starting point of the generation of e-invoices in all supported output formats. Therefore, users of the software do not have to care about all details of other formats but can focus on one.

Why UBL?

In fact, there are just two possible syntaxes for e-invoices conforming to the European standard EN16931, UBL and CII. UBL has been chosen because its syntax is well documented and less complex compared to CII.

At the downside of it, it is currently not possible to add information to invoices that is present in CII but not present in UBL. This may eventually change in the future.

UBL vs Peppol UBL

The Universal Business Language UBL can be used to express a wide variety of business documents, one of them being UBL invoices. The UBL standard is maintained by the organization OASIS Open.

Peppol (Pan-European Public Procurement OnLine) is an effort of the European Union aiming at the standardization of cross-border procurement processes. They have published the Business Interoperability Specifications (BIS), currently version 3.0. One of these specifications is that for UBL Invoice.

This specification is based on the above mentioned UBL specification by OASIS Open but it is not identical. This documentation therefore refers to the Peppol BIS UBL Invoice as Peppol UBL.

Structure of the Peppol UBL Documentation

The UBL invoice documentation is available as either a single HTML page or a multi-page clickable tree.

The single-page version is good for searching but the multi-page version is easier to use and understand.

Document Object Model (DOM)

As UBL is an XML format, the underlying mental model is a Document Object Model (DOM). The software E-Invoice-EU uses JSON instead. The main structural difference to XML - at least in the context of Peppol UBL - is the availability of arrays (lists) in JSON.

Nodes and Leafs

The structure of Peppol UBL consists of nodes which are elements that have sub-elements and leafs which are elements that do not have sub-elements.

Nodes have a namespace prefix of cac, for example the element cac:AccountingSupplierParty which describes the issuer of an invoice. Inside that definition we find the postal address of the supplier and the city part cbc:CityName is a leaf because it does not contain sub-elements. As all other leafs, it has a namespace prefix of cbc.

Cardinality

The Peppol UBL documentation specifies a cardinality of each element. The cardinality describes how many occurences of a certain element are allowed at a certain location. The cardinality is specified as two integers separated by two dots, for example 0..2. The first number specifies the minimum number of occurences and the higher number specifies the maximum number of occurrences. If the higher number is the letter n, as for example in 0..n, there can be an arbitrary number of occurences.

The following table describes typical cardinalities.

Cardinality Meaning
1..1 A mandatory element, for example the amount due of an invoice.
0..1 An optional element, for example an advance payment.
1..n A mandatory list with an unlimited number of elements, for example the line items resp. invoice positions
0..n An optional list with an unlimited number of elements, for example the charges and allowances on document level
1..2 A mandatory list with a maximum of 2 elements, for example the tax total
0..2 An optional list with a maximum of 2 elements, for example the party tax scheme

Rules of thumb: If the first number is 0, an element is optional, otherwise it is mandatory. Only if the second number is greater or equal 2 or it is n, we have a list.

Attributes

XML elements can have attributes that further describe the element's value. For example, the amount due of an invoice has a mandatory attribute @currencyID that contains the abbreviated currency identifier of the amount. In the column "Use" of the attributes section of the element documentation, the letter M indicates that it is a mandatory attribute, in other words, it has to be present.

The company id has an optional attribute schemeID. This is indicated by the letter O in the column "Use".

Code Lists

Many fields cannot have arbitrary values but there a restricted to a choice from a list. These lists are called code lists. The amount due of an invoice for example needs a currency id and the corresponding attribute @currencyID is restricted to the code list ISO 4217 Currency codes. You can get the relevant information by clicking on the element's or attribute's name, and then on the code list name in the section "Code lists". The code list page itself lists the possible values in the section "Codes". You often have to scroll down a little bit to get to the list of values.

Transforming XML to JSON

Since E-Invoice-EU uses JSON and not XML, the Peppol UBL has to be transformed into JSON.

Basic Strategy

The way of transforming XML into JSON for E-Invoice-EU is straightforward and easier to understand than to describe.

The XML structure is converted into JSON by following a simple set of rules:

  1. Elements become JSON keys – Each XML element is represented as a key in the JSON object.
  2. Nesting is preserved – If an element contains child elements, it becomes an object with those elements as its properties.
  3. Text values become string values – If an element contains only text, the text becomes the value of the corresponding key.

Take for example this incomplete fragment of a UBL invoice XML document specifying the supplier's name:

<ubl:Invoice>
  <cac:AccountingSupplierParty>
    <cac:Party>
      <cbc:PartyName>
        Acme Ltd.
      </cbc:PartyName>
    </cac:Party>
  </cac:AccountingSupplierParty>
</ubl:Invoice>

This translates into JSON like this:

{
  "ubl:Invoice": {
    "cac:AccountingSupplierParty": {
      "cac:Party": {
        "cbc:PartyName": "Acme Ltd."
      }
    }
  }
}

Each XML element becomes a property in the JSON object, and the hierarchy remains unchanged. The text content of cbc:PartyName` becomes the string "Acme Ltd." in JSON.

Lists/Arrays

XML has no notion of lists respectively arrays. Instead, elements are simply repeated. Take for example invoice line items:

<ubl:Invoice>
  <cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:AccountingCost>100:1</cbc:AccountingCost>
  </cac:InvoiceLine>
  <cac:InvoiceLine>
    <cbc:ID>2</cbc:ID>
    <cbc:AccountingCost>200:2</cbc:AccountingCost>
  </cac:InvoiceLine>
  <cac:InvoiceLine>
    <cbc:ID>3</cbc:ID>
    <cbc:AccountingCost>300:3</cbc:AccountingCost>
  </cac:InvoiceLine>
</ubl:Invoice>

There are three cac:InvoiceLine elements. That means that they are a list.

The transformation into JSON is straightforward:

{
  "ubl:Invoice": {
    "cac:InvoiceLine": [
      {
        "cbc:ID": "1",
        "cbc:AccountingCost": "100:1",
      },
      {
        "cbc:ID": "2",
        "cbc:AccountingCost": "200:3",
      },
      {
        "cbc:ID": "3",
        "cbc:AccountingCost": "300:3",
      },
    ]
  }
}

Because cac:InvoiceLine is an array (it has a cardinality of 1..n), it is also an array in JSON. The items are simply all sub-nodes of cac:InvoiceLine.

Attributes

Some elements have attributes:

<ubl:Invoice>
  <cac:LegalMonetaryTotal>
    <cbc:PayableAmount currencyID="EUR">23.04</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
</ubl:Invoice>

JSON does not have a notion of attributes. Instead you take the name of the element, add an @ and the attribute name:

{
  "ubl:Invoice": {
    "cac:LegalMonetaryTotal": {
      "cbc:PayableAmount": "23.04"
      "cbc:PayableAmount@currencyID": "EUR"
    }
  }
}

Non-String Values

Please note that strings must be used for all values, even if they are numbers. Check the above examples for that.

Validation

Don't worry if you forget about the exact details. The service bails out with an error message if the structure of the input data does not adhere to the schema.

JSON Schema

If you are familiar with JSON Schema, you can also use this. It is available in the GitHub repo E-Invoice-EU or as the REST endpoint /api/schema/invoice.

Differences to Peppol UBL

At the moment, the only differences to Peppol UBL are, that the fields cbc:CustomizationID and cbc:ProfileID are optional. The reason is that the value of these fields can be deduced from the output format. You only have to specify them if you want to override the built-in default values for them.

This website uses cookies and similar technologies to provide certain features, enhance the user experience and deliver content that is relevant to your interests. Depending on their purpose, analysis and marketing cookies may be used in addition to technically necessary cookies. By clicking on "Agree and continue", you declare your consent to the use of the aforementioned cookies. Here you can make detailed settings or revoke your consent (in part if necessary) with effect for the future. For further information, please refer to our Privacy Policy.