# UBL XML Receipt Format

When a downstream recipient accepts `UBL_PURCHASE_RECEIPT`, the elected owner
device generates a serialized UBL 2.4 XML document. When a recipient accepts
`UBL_INVOICE`, that device can generate UBL Invoice XML instead or in addition.

The device includes only the accepted formats in that recipient's encrypted
document bundle. Cheqi routes the ciphertext and final hashes; it does not
receive the plaintext XML.

The `ubl` field is a **string** — parse it as XML to access the full receipt structure.

## PurchaseReceipt schema

The XML conforms to the following schema:

```openapi
definitionId: PurchaseReceipt
```

## Key elements

| Element | Nullable | Description |
|  --- | --- | --- |
| `id` | No | Unique receipt identifier |
| `issueDate` | No | Date of issue (YYYY-MM-DD) |
| `issueTime` | Yes | Time of issue (HH:MM:SS) |
| `transactionDate` | Yes | Transaction or tax-point date supplied by the issuer |
| `transactionTime` | Yes | Transaction or tax-point time |
| `purchaseDate` | Yes | Purchase or delivery date supplied by the issuer |
| `purchaseTime` | Yes | Purchase or delivery time |
| `documentCurrencyCode` | No | ISO 4217 currency code (e.g. EUR) |
| `note` | Yes | Company-configured free receipt message |
| `accountingSupplierParty` | No | Seller/merchant party details |
| `accountingCustomerParty` | Yes | Buyer party details (B2B) |
| `payment` | Yes | Completed payment metadata, including optional MID/TID |
| `paymentMeans` | No | Payment method information |
| `taxTotals` | No | Tax breakdown per rate |
| `legalMonetaryTotal` | No | Total amounts (tax-exclusive, tax-inclusive, payable) |
| `purchaseReceiptLines` | No | Line items with product, quantity, price, and tax details |
| `verificationNonce` | No | Nonce used for receipt verification |


## XML namespace

The root element uses the UBL 2.4 namespace:

```
urn:oasis:names:specification:ubl:schema:xsd:PurchaseReceipt-2
```

When jurisdictional legal text is present, the root also declares the standard
UBL extension namespace and Cheqi's extension namespace:

```xml
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:cheqi="urn:cheqi:ubl:extension:components:1"
```

## Example

```xml
<?xml version="1.0" encoding="UTF-8"?>
<PurchaseReceipt
    xmlns="urn:oasis:names:specification:ubl:schema:xsd:PurchaseReceipt-2"
    xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
    xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
  <cbc:ID>INV-2026-001</cbc:ID>
  <cbc:IssueDate>2026-03-20</cbc:IssueDate>
  <cbc:Note>Thank you for shopping with us.</cbc:Note>
  <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
  <cac:AccountingSupplierParty>
    <!-- Party details -->
  </cac:AccountingSupplierParty>
  <cac:Payment>
    <cbc:MerchantID>MID-123456</cbc:MerchantID>
    <cbc:PaymentTerminalID>TID-987654</cbc:PaymentTerminalID>
  </cac:Payment>
  <cac:PaymentMeans>
    <cbc:PaymentMeansCode listID="UN/ECE 4461">48</cbc:PaymentMeansCode>
    <cac:CardAccount>
      <cbc:PrimaryAccountNumberID>4242</cbc:PrimaryAccountNumberID>
      <cbc:NetworkID>VISA</cbc:NetworkID>
    </cac:CardAccount>
  </cac:PaymentMeans>
  <cac:LegalMonetaryTotal>
    <cbc:TaxExclusiveAmount currencyID="EUR">10.00</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="EUR">12.10</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="EUR">12.10</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
  <cac:PurchaseReceiptLine>
    <cbc:ID>1</cbc:ID>
    <cac:Item>
      <cbc:Name>Coffee</cbc:Name>
    </cac:Item>
    <cac:Price>
      <cbc:PriceAmount currencyID="EUR">5.00</cbc:PriceAmount>
    </cac:Price>
  </cac:PurchaseReceiptLine>
</PurchaseReceipt>
```

## Free receipt message and jurisdictional text

The company configures its free receipt message in the Cheqi app. The local
engine places that text in CHEQI `note` and UBL `cbc:Note`. A merchant does not
send it in each `ReceiptPayload`.

Jurisdictional wording has a different purpose and never uses `cbc:Note`.
Values supplied through `jurisdictionalData.legalTexts[]` are preserved in
CHEQI JSON and written to a structured extension in UBL PurchaseReceipt,
Invoice, and CreditNote:

```xml
<ext:UBLExtensions>
  <ext:UBLExtension>
    <ext:ExtensionAgencyID>CHEQI</ext:ExtensionAgencyID>
    <ext:ExtensionVersionID>1</ext:ExtensionVersionID>
    <ext:ExtensionURI>urn:cheqi:ubl:extension:jurisdictional-legal-text:1</ext:ExtensionURI>
    <ext:ExtensionContent>
      <cheqi:JurisdictionalLegalTexts>
        <cheqi:LegalText
            code="BE:GKS_DOCUMENT_HEADING"
            displayRole="DOCUMENT_HEADING"
            languageCode="nl-BE">BTW-KASTICKET</cheqi:LegalText>
      </cheqi:JurisdictionalLegalTexts>
    </ext:ExtensionContent>
  </ext:UBLExtension>
</ext:UBLExtensions>
```

The extension URI and element shape are identical in UBL Invoice. A receiving
application can use `displayRole` to render a heading, notice, or footer without
interpreting general-purpose note text.

## Merchant and payment terminal identifiers

For a card payment, recipient resolution can supply two optional payment
metadata fields. They appear in the locally generated CHEQI JSON as:

```json
{
  "paymentMeans": {
    "paymentMeansCode": "48",
    "cardProvider": "VISA",
    "cardLastFour": "4242",
    "merchantId": "MID-123456",
    "paymentTerminalId": "TID-987654"
  }
}
```

The Rust engine maps those fields natively in UBL 2.4 PurchaseReceipt:

| CHEQI JSON | PurchaseReceipt |
|  --- | --- |
| `paymentMeans.merchantId` | `cac:Payment/cbc:MerchantID` |
| `paymentMeans.paymentTerminalId` | `cac:Payment/cbc:PaymentTerminalID` |


Both values are optional. They are receipt metadata only and are never used to
match a customer. `paymentTerminalId` is the card-payment terminal identifier;
it is not a fiscal cash-register, fiscal-device, or jurisdictional terminal
identifier.

Cheqi currently applies this native mapping to UBL PurchaseReceipt only. Do not
assume that the same elements are present in UBL Invoice.

## Related

- [Receipt Creation](/receipts/creation) — how to build the encrypted generation input
- [Receipt Flow Overview](/receipts/overview) — full receipt lifecycle
- [Receipt Verification](/verification/verification) — verifying receipt integrity