# Receipt Creation

Receipt creation begins with a definitive merchant-supplied `ReceiptPayload`.
This plaintext object exists only in merchant-controlled memory. The SDK
serializes and encrypts it separately for each owner device returned by
recipient resolution; Cheqi never receives it in plaintext.

The current Java and JavaScript SDKs expose this object as `ReceiptPayload`. In
the digital flow it is an input to local encryption and on-device generation;
it is not sent to a plaintext template endpoint.

## Required values

The issuer supplies these values:

| Field | Meaning |
|  --- | --- |
| `documentNumber` | Issuer-assigned receipt number |
| `issueDate` | Date and time the issuer created the receipt |
| `currency` | ISO 4217 currency code |
| `receiptSubtotal` | Issuer-calculated subtotal |
| `totalBeforeTax` | Issuer-calculated total excluding tax |
| `totalTaxAmount` | Issuer-calculated tax total |
| `totalAmount` | Issuer-calculated final amount |
| `taxesApplied` | Whether taxes apply to this receipt |
| `products` | Receipt line items |


The SDK and mobile generator do not calculate fiscal totals, tax, signatures,
sequences, or QR values for the issuer. Supply the legally definitive values
from the POS or commerce system.

## Optional values

Common optional fields include:

- `identifiers` for issuer and transaction references
- `discounts` and `charges`
- `taxes` for the receipt-level tax breakdown
- `transactionDate` and `purchaseDate`
- `period` for billing or service periods
- `barcodes`
- `paymentDetails`
- `jurisdictionalData` for country-specific fiscal and legal information


The free receipt message is configured on the company in the Cheqi app. It is
not supplied in each `ReceiptPayload`. The local engine uses that configured
message for CHEQI `note` and UBL `cbc:Note`.

`paymentDetails` is the definitive issuer-supplied payment object. It remains
inside the encrypted receipt payload. The owner device passes it unchanged to
the local generator; server-known matching data does not replace or merge into
it.

## Country-specific receipts

Use `jurisdictionalData` when your POS, fiscal device, or invoicing system has
country-specific data that must remain attached to the receipt. This includes
external regime identifiers, exact legal wording, fiscalization evidence,
authority references, and namespaced extension fields.

Cheqi preserves supplied country data but does not decide which local regime
applies to a transaction or manufacture authority data. See
[Country Support](/countries/overview) for the supported country set and
[Supplying Jurisdiction Data](/countries/jurisdictional-data) for the
request shape.

## Plaintext shape before encryption

The exact schema is available as `ReceiptPayload` in the API reference. A
minimal illustrative payload looks like this:

```json
{
  "documentNumber": "INV-2026-001",
  "issueDate": "2026-08-02T14:35:02Z",
  "currency": "EUR",
  "receiptSubtotal": 10.00,
  "totalBeforeTax": 10.00,
  "totalTaxAmount": 2.10,
  "totalAmount": 12.10,
  "taxesApplied": true,
  "products": [
    {
      "name": "Coffee",
      "identifier": "SKU-COFFEE-001",
      "quantity": 2,
      "unitCode": "C62",
      "unitPrice": 5.00,
      "subtotal": 10.00,
      "total": 12.10,
      "taxes": [
        {
          "rate": 21.0,
          "type": "VAT",
          "taxableAmount": 10.00,
          "amount": 2.10
        }
      ]
    }
  ],
  "taxes": [
    {
      "rate": 21.0,
      "type": "VAT",
      "taxableAmount": 10.00,
      "amount": 2.10,
      "label": "VAT 21%"
    }
  ],
  "paymentDetails": {
    "paymentMeansCode": "48",
    "description": "Card",
    "cardProvider": "VISA",
    "cardLastFour": "4242"
  }
}
```

This example is plaintext for explanation only. Do not send this JSON directly
to `/receipt/encrypted`.

## Per-device encryption

For every temporary owner-device recipient returned by
`POST /recipient/resolve`:

1. serialize the same definitive `ReceiptPayload`
2. generate a fresh AES-256 content key
3. encrypt the serialized payload with AES-GCM
4. wrap that content key with the recipient's public key
5. submit the recipient ID, ciphertext, and wrapped key as one
`deviceDeliveries` entry


Do not reuse a symmetric key across devices. Submit exactly one entry for every
device returned by the match and no additional recipients.

## Product identifiers

Every product line requires an `identifier`: the SKU, article number, or other
issuer-controlled key for that line. Make it unique within the receipt.

That identifier is also the durable key used in return flows. When a customer
returns an item, it comes back as the `lineItemId`, allowing the issuer to map
the return to the original line. See
[Receiving Return Requests](/creditnote/receiving-returns#matching-returns-to-your-receipt-lines).

## What happens on the phone

After decryption, the owner device combines the merchant payload with the
current supplier, customer, optional store, and routing context that Cheqi
already knows. The shared Rust engine then generates and hashes the local CHEQI
receipt.

The one device holding the downstream distribution lease also generates the UBL
formats required by the resolved recipients. Those final documents are bundled
and encrypted on the device. The backend receives ciphertext and hashes, not the
plaintext CHEQI JSON or UBL XML.

Continue with [Sending Receipts](/receipts/sending) for the submission contract.