{
    "$id": "https://se.receipts.kivra.com/schemas/json/retail/v2.0",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "description": "digital receipt schema",
    "type": "object",
    "properties": {
        "copy": {
            "type": "boolean",
            "default": false,
            "description": "If true the receipt is a copy"
        },
        "business_unit": {
            "description": "Merchant information",
            "$ref": "#/$defs/business_information"
        },
        "cashier": {
            "description": "Identifies the person handling the purchase if applicable",
            "$ref": "#/$defs/cashier"
        },
        "sales_recording_system": {
            "description": "Information about the point of sales system used. The system producing the receipt",
            "$ref": "#/$defs/sales_recording_system"
        },
        "receipt_identifier": {
            "description": "Receipt identifiers: sequence number and/or extended number with or without barcode representation",
            "$ref": "#/$defs/receipt_identifier"
        },
        "time_of_purchase": {
            "description": "ISO 8601 date/time format: YYYY-MM-DDThh:mm:ssTZD",
            "type": "string",
            "format": "date-time"
        },
        "currency": {
            "description": "The receipt default currency. This gives the currency for all amounts in the receipt. If applicable overriding currencies can be added to the tender parts",
            "$ref": "#/$defs/currency_code"
        },
        "totals": {
            "description": "Total amounts keyed by type, e.g. {\"gross\": {...}, \"vat\": {...}}.",
            "type": "object",
            "properties": {
                "paid": {
                    "$ref": "#/$defs/total_paid_element"
                },
                "gross": {
                    "$ref": "#/$defs/total_gross_element"
                },
                "vat": {
                    "$ref": "#/$defs/total_tax_element"
                },
                "net": {
                    "$ref": "#/$defs/total_net_element"
                },
                "loyalty": {
                    "$ref": "#/$defs/total_loyalty_element"
                },
                "rounding": {
                    "$ref": "#/$defs/total_rounding_element"
                },
                "tip": {
                    "$ref": "#/$defs/total_tip_element"
                },
                "modifiers": {
                    "$ref": "#/$defs/total_modifiers_element"
                }
            },
            "additionalProperties": false
        },
        "header_text": {
            "description": "Any textual information aimed for the receipt header",
            "type": "string"
        },
        "footer_text": {
            "description": "Any textual information aimed for the receipt footer",
            "type": "string"
        },
        "items": {
            "description": "List of receipt items, goods or services sold/returned. Each entry is a single-key object naming the item type, e.g. {\"sale\": {...}}. The key implies the type, so it need not be repeated inside the value.",
            "type": "array",
            "items": {
                "type": "object",
                "minProperties": 1,
                "maxProperties": 1,
                "additionalProperties": false,
                "properties": {
                    "sale": {
                        "$ref": "#/$defs/sale_item"
                    },
                    "return": {
                        "$ref": "#/$defs/return_item"
                    },
                    "text": {
                        "$ref": "#/$defs/text_item"
                    },
                    "deposit": {
                        "$ref": "#/$defs/deposit_item"
                    }
                }
            }
        },
        "modifiers": {
            "type": "array",
            "description": "Receipt-level price modifiers (discounts/surcharges) that apply to the whole receipt and cannot be attributed to individual lines — for example a 5% discount on the entire purchase, spread pro-rata across its VAT rates. If the POS can attribute a modifier to specific lines it does not belong here: put it on those lines' own modifiers instead (e.g. a discount on a single item). Distinct from totals.modifiers, which is the aggregate discount/surcharge checksum derived from these.",
            "items": {
                "$ref": "#/$defs/price_modifier_element"
            }
        },
        "payments": {
            "description": "Tender related information, several tender types can be used for payment",
            "type": "array",
            "items": {
                "$ref": "#/$defs/tender_element"
            }
        },
        "customer": {
            "description": "Identification and information about the customer",
            "$ref": "#/$defs/customer"
        },
        "customer_order": {
            "description": "Information about a connected customer order if applicable",
            "$ref": "#/$defs/customer_order_information"
        },
        "control_unit": {
            "description": "Control unit information required by swedish tax authorities",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string"
                },
                "code": {
                    "type": "string"
                }
            },
            "required": [
                "id"
            ],
            "additionalProperties": false
        }
    },
    "required": [
        "business_unit",
        "sales_recording_system",
        "receipt_identifier",
        "time_of_purchase",
        "currency",
        "totals",
        "items",
        "payments"
    ],
    "additionalProperties": false,
    "$defs": {
        "organization_number": {
            "type": "string",
            "description": "Swedish organisationsnummer (10 digits, optionally hyphenated). A VAT number must be sent in vat_number, not here.",
            "pattern": "^[0-9]{6}-?[0-9]{4}$"
        },
        "vat_number": {
            "type": "string",
            "description": "VAT registration number incl. country prefix (SE/NO/DK/FI), accepted as an alternative to organization_number. A plain Swedish organisationsnummer must go in organization_number, not here.",
            "examples": [
                "SE556677889901",
                "NO123456789MVA",
                "DK99999999",
                "FI99999999"
            ],
            "pattern": "^(SE[0-9]{12}|NO[0-9]{9}(?:[Mm][Vv][Aa])?|DK[0-9]{8}|FI[0-9]{8})$"
        },
        "country_code": {
            "title": "country code",
            "description": "Country as an ISO 3166-1 alpha-3 code, e.g. SWE. Case-insensitive.",
            "type": "string",
            "pattern": "^[A-Za-z]{3}$"
        },
        "address": {
            "title": "address",
            "description": "An address following the convention of http://microformats.org/wiki/hcard. At least one of street_address or post_box is required.",
            "type": "object",
            "properties": {
                "street_address": {
                    "type": "string"
                },
                "extended_address": {
                    "type": "string"
                },
                "post_box": {
                    "type": "string"
                },
                "locality": {
                    "type": "string"
                },
                "postal_code": {
                    "type": "string"
                },
                "region": {
                    "type": "string"
                },
                "country_code": {
                    "$ref": "#/$defs/country_code"
                },
                "type": {
                    "title": "address type",
                    "description": "Whether the address relates to a business or a home",
                    "type": "string",
                    "enum": [
                        "home",
                        "business"
                    ]
                }
            },
            "anyOf": [
                {
                    "title": "Street address",
                    "required": [
                        "street_address"
                    ]
                },
                {
                    "title": "Post box address",
                    "required": [
                        "post_box"
                    ]
                }
            ],
            "required": [
                "locality",
                "postal_code"
            ],
            "additionalProperties": false
        },
        "phone_number": {
            "title": "generic phone number",
            "description": "generic format for phone numbers where strict format can not be enforced, use only for phone number to be displayed",
            "type": "string",
            "pattern": "^(\\(?((\\+|(00))[0-9]{1,3})\\)?)?( ?-?\\(?[0-9]+\\)?)+$"
        },
        "geo_location": {
            "type": "object",
            "$comment": "No additionalProperties:false — shared with the draft-07 ps family; tightening it here would change ps behavior on its next regeneration.",
            "title": "Geographic location (long/lat)",
            "description": "A geographical coordinate",
            "properties": {
                "latitude": {
                    "type": "number"
                },
                "longitude": {
                    "type": "number"
                }
            },
            "required": [
                "latitude",
                "longitude"
            ]
        },
        "business_information": {
            "type": "object",
            "description": "Merchant/business unit information. A stable external_id or existing service_id is required. organization_number or vat_number may be omitted when that id resolves an existing, authorized store; identity-less receipts cannot create companies.",
            "properties": {
                "name": {
                    "type": "string"
                },
                "service_id": {
                    "description": "Kivra id of an existing business unit.",
                    "type": "string",
                    "minLength": 42,
                    "maxLength": 42,
                    "pattern": "^[0-9]{10}[0-9a-fA-F]{32}$"
                },
                "unit_id": {
                    "type": "string",
                    "description": "Internal merchant shop/business unit id"
                },
                "external_id": {
                    "type": "string",
                    "description": "Partner's own stable identifier for the store. The store is deduped on (owning chain, external_id), so a partner keeps one store per external_id."
                },
                "organization_number": {
                    "$ref": "#/$defs/organization_number"
                },
                "vat_number": {
                    "$ref": "#/$defs/vat_number"
                },
                "contact": {
                    "type": "object",
                    "description": "Merchant contact information name, address, phone etc",
                    "properties": {
                        "address": {
                            "$ref": "#/$defs/address"
                        },
                        "email": {
                            "type": "string",
                            "format": "email"
                        },
                        "phone": {
                            "$ref": "#/$defs/phone_number"
                        },
                        "website": {
                            "type": "string",
                            "format": "uri"
                        }
                    },
                    "additionalProperties": false
                },
                "geo_location": {
                    "$ref": "#/$defs/geo_location"
                },
                "chain": {
                    "type": "object",
                    "description": "Optional chain grouping for the store. Reference an existing chain with service_id, or supply name plus organization_number, vat_number, or external_id to group the store under a chain that is created on first use. organization_number/vat_number follow the same semantics as on the wrapping business unit. When omitted, the store is grouped under the default chain (one per the store's own organization/VAT number per partner).",
                    "properties": {
                        "service_id": {
                            "description": "Kivra id of an existing chain. When present, references that chain directly; name/organization_number/vat_number/external_id are then not required.",
                            "type": "string",
                            "minLength": 42,
                            "maxLength": 42,
                            "pattern": "^[0-9]{10}[0-9a-fA-F]{32}$"
                        },
                        "name": {
                            "type": "string",
                            "description": "Display name of the chain. Required when the chain may need to be created (i.e. when service_id is absent)."
                        },
                        "organization_number": {
                            "description": "Swedish organisationsnummer (10 digits, optionally hyphenated) of the chain. A VAT number must be sent in vat_number, not here. Grouping key when external_id is absent.",
                            "$ref": "#/$defs/organization_number"
                        },
                        "vat_number": {
                            "description": "Chain VAT registration number incl. country prefix (SE/NO/DK/FI), accepted as an alternative to organization_number. A plain Swedish organisationsnummer must go in organization_number, not here. Grouping key when external_id is absent.",
                            "$ref": "#/$defs/vat_number"
                        },
                        "external_id": {
                            "type": "string",
                            "description": "Partner's own stable identifier for the chain. Grouping key when no organization_number/vat_number is given."
                        }
                    },
                    "anyOf": [
                        {
                            "title": "Existing chain referenced by service_id",
                            "required": [
                                "service_id"
                            ]
                        },
                        {
                            "title": "Chain identified by name and organization number",
                            "required": [
                                "name",
                                "organization_number"
                            ]
                        },
                        {
                            "title": "Chain identified by name and VAT number",
                            "required": [
                                "name",
                                "vat_number"
                            ]
                        },
                        {
                            "title": "Chain identified by name and partner external id",
                            "required": [
                                "name",
                                "external_id"
                            ]
                        }
                    ],
                    "additionalProperties": false
                }
            },
            "required": [
                "name",
                "contact"
            ],
            "anyOf": [
                {
                    "title": "Existing business unit referenced by service_id",
                    "required": [
                        "service_id"
                    ]
                },
                {
                    "title": "Pre-provisioned business unit referenced by external_id",
                    "required": [
                        "external_id"
                    ]
                },
                {
                    "title": "Identified by external_id and organization number",
                    "required": [
                        "external_id",
                        "organization_number"
                    ]
                },
                {
                    "title": "Identified by external_id and VAT number",
                    "required": [
                        "external_id",
                        "vat_number"
                    ]
                },
                {
                    "title": "Identified by service_id and organization number",
                    "required": [
                        "service_id",
                        "organization_number"
                    ]
                },
                {
                    "title": "Identified by service_id and VAT number",
                    "required": [
                        "service_id",
                        "vat_number"
                    ]
                }
            ],
            "additionalProperties": false
        },
        "cashier": {
            "title": "cashier name and id",
            "description": "information about the cashier, optional",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                }
            },
            "additionalProperties": false
        },
        "pos_information": {
            "title": "point of sales system",
            "description": "information that somehow identifies the pos system. At least one of id or name is required.",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "serial_number": {
                    "type": "string"
                }
            },
            "anyOf": [
                {
                    "title": "POS identified by id",
                    "required": [
                        "id"
                    ]
                },
                {
                    "title": "POS identified by name",
                    "required": [
                        "name"
                    ]
                }
            ],
            "additionalProperties": false
        },
        "sales_recording_system": {
            "title": "sales recording system information",
            "description": "A sales recording system is any system where the sales is registered. Example POS",
            "$ref": "#/$defs/pos_information"
        },
        "barcode_element": {
            "type": "string",
            "enum": [
                "Interleaved2Of5",
                "EAN13",
                "EAN8",
                "Codabar",
                "Code39",
                "Code93",
                "Code128",
                "AztecCode",
                "Datamatrix",
                "PDF417",
                "QRCode"
            ],
            "description": "barcode representation of any data"
        },
        "extended_receipt_number_type": {
            "type": "object",
            "$comment": "No additionalProperties:false — shared with the draft-07 ps family; tightening it here would change ps behavior on its next regeneration.",
            "description": "a more complex receipt number if applicable, must be unique in given context",
            "properties": {
                "value": {
                    "type": "string",
                    "description": "data that will be presented as a barcode on the receipt"
                },
                "type": {
                    "$ref": "#/$defs/barcode_element"
                },
                "context": {
                    "type": "string",
                    "enum": [
                        "store",
                        "chain",
                        "global"
                    ],
                    "description": "in what context is the value (receipt number) unique, note GLOBAL can only be used if a digital receipt provider receipt id is used"
                }
            },
            "required": [
                "value",
                "context"
            ]
        },
        "receipt_identifier": {
            "title": "receipt identifier",
            "description": "a receipt is often identified by a sequence number and/or an extended id (unique in some context) with or without a barcode representation.",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "type": "integer",
                    "description": "a sequence number as stipulated by the swedish tax authorities"
                },
                "extended_number": {
                    "$ref": "#/$defs/extended_receipt_number_type"
                }
            },
            "required": [
                "sequence_number"
            ],
            "additionalProperties": false
        },
        "currency_code": {
            "title": "ISO-4217 currency codes",
            "description": "ISO 4217 currency code, e.g.: USD, EUR, CHF",
            "type": "string",
            "pattern": "^[a-zA-Z]{3}$"
        },
        "total_paid_element": {
            "title": "Paid total amount",
            "description": "paid: gross amount including discount and rounding.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed paid total: negative when money goes back to the customer (e.g. a return)."
                },
                "received": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Amount received from the customer (e.g. cash tendered), when it differs from the paid amount."
                },
                "returned": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Amount returned to the customer (e.g. change given), when applicable."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_gross_element": {
            "title": "Total gross amount presented on the receipt",
            "description": "gross: total including vat, after line price replacements but before discounts and surcharges",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed gross total: negative when money goes back to the customer (e.g. a return)."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "sub_total_vat": {
            "title": "Sub totals can be used on all totals but is mostly used on VAT",
            "description": "One or more sub totals, exactly one per distinct tax percentage. Every line and modifier at a given rate is aggregated into that rate's single bucket. Monetary fields are signed (see amount).",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed amount for this VAT bucket: the signed sum of every line and modifier at this tax_percentage. Because there is one bucket per rate, opposite-direction entries at the same rate cancel — e.g. a +15 kr sale and a −15 kr return, both at 15%, aggregate into a single 15% bucket with amount 0. Negative when returns at the rate outweigh sales."
                },
                "taxable_amount": {
                    "description": "Amount including tax amount (signed, same direction as amount).",
                    "type": "number"
                },
                "net_amount": {
                    "description": "Amount excluding tax amount (signed, same direction as amount).",
                    "type": "number"
                },
                "tax_percentage": {
                    "type": "number",
                    "minimum": 0
                }
            },
            "required": [
                "amount",
                "taxable_amount",
                "net_amount",
                "tax_percentage"
            ],
            "additionalProperties": false
        },
        "total_tax_element": {
            "title": "Total tax amount presented on the receipt",
            "description": "Tax releated total",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed tax total: negative when money goes back to the customer (e.g. a return)."
                },
                "sub_totals": {
                    "type": "array",
                    "description": "add sub total for each tax percentage used",
                    "items": {
                        "$ref": "#/$defs/sub_total_vat"
                    }
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_net_element": {
            "title": "Total net amount presented on the receipt",
            "description": "net: total excluding vat",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed net total: negative when money goes back to the customer (e.g. a return)."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_loyalty_element": {
            "title": "Total loyalty amount",
            "description": "Total loyalty points/amount redeemed. Amount only — no breakdown applies.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "minimum": 0
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_rounding_element": {
            "title": "Total rounding amount",
            "description": "Rounding adjustment applied to reach the paid amount. Amount only — no breakdown applies.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed rounding adjustment (may be negative)."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_tip_element": {
            "title": "Total tip amount",
            "description": "Tip included in paid but excluded from gross, net, and VAT. A positive amount is a tip from the customer.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number"
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_modifier_amount_element": {
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Positive magnitude; the enclosing discount/surcharge key carries the direction."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "total_modifiers_element": {
            "title": "Modifier totals",
            "description": "Aggregate discount and surcharge totals. Both are fully derivable from the line- and receipt-level discount/surcharge modifiers (a checksum), so either may be omitted. Line price replacements establish the gross baseline and are not included. If sent, provide at least one.",
            "type": "object",
            "minProperties": 1,
            "properties": {
                "discount": {
                    "$ref": "#/$defs/total_modifier_amount_element"
                },
                "surcharge": {
                    "$ref": "#/$defs/total_modifier_amount_element"
                }
            },
            "additionalProperties": false
        },
        "item_identifier": {
            "title": "Item identifier",
            "description": "Identifier for an item being sold or returned. Supported types: 'pos' (Point of Sale identifier) and 'gtin' (Global Trade Item Number).",
            "type": "object",
            "properties": {
                "identifier_type": {
                    "type": "string",
                    "enum": [
                        "pos",
                        "gtin"
                    ]
                },
                "value": {
                    "type": "string"
                }
            },
            "required": [
                "identifier_type",
                "value"
            ],
            "additionalProperties": false
        },
        "entry_method_elment": {
            "type": "string",
            "enum": [
                "smartcard",
                "micr",
                "msr",
                "keyed",
                "scanned",
                "weighed",
                "measured",
                "rfid",
                "automatic",
                "integrated_chip_card",
                "tapped",
                "waved"
            ],
            "default": "scanned"
        },
        "quantity_element": {
            "type": "object",
            "properties": {
                "value": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "description": "Quantity sold/returned/covered. Must be > 0: a line for zero units is not a real sale, and it would make the per-unit price (actual_sales_unit_price = extended_amount / quantity) underivable."
                },
                "unit": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 25,
                    "pattern": "\\S",
                    "description": "Unit for this quantity; we recommend following a standard such as UN/CEFACT Rec 20. Must contain at least one non-whitespace character."
                },
                "entry_method": {
                    "$ref": "#/$defs/entry_method_elment"
                }
            },
            "required": [
                "value",
                "unit"
            ],
            "additionalProperties": false
        },
        "price_modifier": {
            "title": "Price modifier value",
            "description": "The value of a discount or surcharge (direction is set by the enclosing key). amount is authoritative; percent, base_amount and quantity are informational only.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Required, authoritative monetary magnitude (VAT-inclusive), always positive. Direction is carried by the enclosing discount/surcharge key."
                },
                "description": {
                    "type": "string",
                    "description": "Human-readable label for the modifier, e.g. \"Member offer −10%\"."
                },
                "reason": {
                    "type": "string",
                    "enum": [
                        "loyalty",
                        "coupon",
                        "campaign",
                        "employee",
                        "staff",
                        "damage",
                        "price_match",
                        "other"
                    ],
                    "description": "Optional category of the modifier."
                },
                "percent": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Informational: the percentage applied (always positive)."
                },
                "base_amount": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Informational: the amount the percent applied to."
                },
                "quantity": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Informational: how many times the modifier was applied. Might not equal the item quantity. Example: 2 coupons '3 for 2' on six items — item quantity 6, modifier quantity 2."
                },
                "tax_percentage": {
                    "type": "number",
                    "minimum": 0,
                    "description": "VAT-bucket routing key: the tax rate the modifier's (VAT-inclusive) amount belongs to. Send only when it differs from the affected line's rate."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "price_replacement": {
            "title": "Line price replacement",
            "description": "Replaces the line's gross amount. It cannot be combined with another modifier on the same line.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "The final signed, VAT-inclusive amount for the whole line before receipt-level modifiers. It must equal the line's extended_amount. Use a negative amount on a return line."
                },
                "description": {
                    "type": "string",
                    "description": "Human-readable reason for the price replacement."
                }
            },
            "required": [
                "amount"
            ],
            "additionalProperties": false
        },
        "line_price_modifier_element": {
            "title": "Line price modifier",
            "description": "A line-level discount, surcharge, or price replacement. A replacement establishes the line's gross amount before any receipt-level modifiers.",
            "type": "object",
            "minProperties": 1,
            "maxProperties": 1,
            "additionalProperties": false,
            "properties": {
                "discount": {
                    "$ref": "#/$defs/price_modifier"
                },
                "surcharge": {
                    "$ref": "#/$defs/price_modifier"
                },
                "replace": {
                    "$ref": "#/$defs/price_replacement"
                }
            }
        },
        "foreign_currency": {
            "title": "Foreign currency",
            "description": "Gives exchange rate etc when payment is done with a foreign currency",
            "type": "object",
            "properties": {
                "currency": {
                    "description": "ISO 4217 foreign currency code",
                    "$ref": "#/$defs/currency_code"
                },
                "original_face_amount": {
                    "description": "the original amount in the foreign currency the being converted to local currency.  For example, converting Yen to Dollars, this amount would be the amount of Yen",
                    "type": "number",
                    "minimum": 0
                },
                "exchange_rate": {
                    "type": "number",
                    "minimum": 0
                }
            },
            "required": [
                "currency",
                "original_face_amount"
            ],
            "additionalProperties": false
        },
        "sale_item": {
            "description": "Defines data needed to handle sold product/service",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "description": "All items must have a unique sequence number 1,2,3 etc. Used for internal references. Also see item_link",
                    "type": "integer"
                },
                "item_link": {
                    "description": "A reference to an other items sequence_number if a relation exists",
                    "type": "integer"
                },
                "text": {
                    "type": "string"
                },
                "identifiers": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "$ref": "#/$defs/item_identifier"
                    }
                },
                "serial_number": {
                    "description": "Product serial number",
                    "type": "string"
                },
                "lot_number": {
                    "description": "Specifies a specific product batch/lot",
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "quantity": {
                    "$ref": "#/$defs/quantity_element"
                },
                "eligible_for_frequent_shopper_points": {
                    "type": "boolean",
                    "default": false,
                    "description": "true if item bought is eligible for bonus"
                },
                "unit_cost_price": {
                    "type": "number",
                    "description": "The unit cost of the item to the merchant at the time of the Transaction."
                },
                "regular_sales_unit_price": {
                    "type": "number",
                    "description": "Optional: the undiscounted per-unit price the merchant printed, before any discounts or surcharges."
                },
                "actual_sales_unit_price": {
                    "type": "number",
                    "description": "Optional: the authoritative per-unit price the merchant printed, net of discounts/surcharges, carried through for faithful display. When omitted, consumers derive extended_amount / quantity. It is kept as a field (not dropped as \"derivable\") because the printed price is independently rounded, so the quotient can differ from what the customer saw on the paper receipt. extended_amount remains the authoritative line total."
                },
                "extended_amount": {
                    "type": "number",
                    "description": "The amount the customer paid for this line, net of any line-level modifiers (VAT-inclusive). Authoritative for the line total."
                },
                "modifiers": {
                    "type": "array",
                    "description": "Line-level price modifiers already reflected in extended_amount. A replace modifier sets the final signed, VAT-inclusive amount for the whole line and cannot be combined with another line modifier. It establishes the line's gross baseline before receipt-level discounts/surcharges are applied.",
                    "items": {
                        "$ref": "#/$defs/line_price_modifier_element"
                    },
                    "allOf": [
                        {
                            "if": {
                                "contains": {
                                    "type": "object",
                                    "required": [
                                        "replace"
                                    ]
                                }
                            },
                            "then": {
                                "maxItems": 1
                            }
                        }
                    ]
                },
                "tax_percentage": {
                    "type": "number"
                },
                "tax_amount": {
                    "description": "tax amount based on extended amount and tax percentage",
                    "type": "number"
                },
                "foreign_currency": {
                    "$ref": "#/$defs/foreign_currency"
                }
            },
            "required": [
                "sequence_number",
                "identifiers",
                "description",
                "quantity",
                "extended_amount"
            ],
            "additionalProperties": false
        },
        "return_item": {
            "description": "Defines data needed to handle returned product/service",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "description": "All items must have a unique sequence number 1,2,3 etc. Used for internal references. Also see item_link",
                    "type": "integer"
                },
                "item_link": {
                    "description": "A reference to an other items sequence_number if a relation exists",
                    "type": "integer"
                },
                "text": {
                    "type": "string"
                },
                "receipt_reference": {
                    "$ref": "#/$defs/extended_receipt_number_type"
                },
                "identifiers": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "$ref": "#/$defs/item_identifier"
                    }
                },
                "serial_number": {
                    "description": "Product serial number",
                    "type": "string"
                },
                "lot_number": {
                    "description": "Specifies a specific product batch/lot",
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "quantity": {
                    "$ref": "#/$defs/quantity_element"
                },
                "eligible_for_frequent_shopper_points": {
                    "type": "boolean",
                    "default": false,
                    "description": "true if item bought is eligible for bonus"
                },
                "unit_cost_price": {
                    "type": "number",
                    "description": "The unit cost of the item to the merchant at the time of the Transaction."
                },
                "regular_sales_unit_price": {
                    "type": "number",
                    "description": "Optional: the undiscounted per-unit price the merchant printed, before any discounts or surcharges."
                },
                "actual_sales_unit_price": {
                    "type": "number",
                    "description": "Optional: the authoritative per-unit price the merchant printed, net of discounts/surcharges, carried through for faithful display. When omitted, consumers derive extended_amount / quantity. It is kept as a field (not dropped as \"derivable\") because the printed price is independently rounded, so the quotient can differ from what the customer saw on the paper receipt. extended_amount remains the authoritative line total."
                },
                "extended_amount": {
                    "type": "number",
                    "description": "The amount the customer paid for this line, net of any line-level modifiers (VAT-inclusive). Authoritative for the line total."
                },
                "modifiers": {
                    "type": "array",
                    "description": "Line-level price modifiers already reflected in extended_amount. A replace modifier sets the final signed, VAT-inclusive amount for the whole line and cannot be combined with another line modifier. It establishes the line's gross baseline before receipt-level discounts/surcharges are applied.",
                    "items": {
                        "$ref": "#/$defs/line_price_modifier_element"
                    },
                    "allOf": [
                        {
                            "if": {
                                "contains": {
                                    "type": "object",
                                    "required": [
                                        "replace"
                                    ]
                                }
                            },
                            "then": {
                                "maxItems": 1
                            }
                        }
                    ]
                },
                "tax_percentage": {
                    "type": "number"
                },
                "tax_amount": {
                    "description": "tax amount based on extended amount and tax percentage",
                    "type": "number"
                },
                "foreign_currency": {
                    "$ref": "#/$defs/foreign_currency"
                }
            },
            "required": [
                "sequence_number",
                "identifiers",
                "description",
                "quantity",
                "extended_amount"
            ],
            "additionalProperties": false
        },
        "text_item": {
            "description": "Text only item, example: product warranty text linked to item purchased",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "description": "All items must have a unique sequence number 1,2,3 etc. Used for internal references. Also see item_link",
                    "type": "integer"
                },
                "item_link": {
                    "description": "A reference to an other items sequence_number if a relation exists",
                    "type": "integer"
                },
                "text": {
                    "type": "string"
                }
            },
            "required": [
                "sequence_number",
                "text"
            ],
            "additionalProperties": false
        },
        "sub_deposits_vat": {
            "title": "VAT sub deposit",
            "description": "A deposit can be divided into different VATs.",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed deposit amount for this VAT bucket: negative when it is returned to the customer (a deposit return)"
                },
                "tax_percentage": {
                    "type": "number",
                    "minimum": 0
                }
            },
            "required": [
                "amount",
                "tax_percentage"
            ],
            "additionalProperties": false
        },
        "deposit_item": {
            "description": "Deposit to get or pay connected to items sold/returned",
            "type": "object",
            "properties": {
                "sequence_number": {
                    "description": "All items must have a unique sequence number 1,2,3 etc. Used for internal references. Also see item_link",
                    "type": "integer"
                },
                "item_link": {
                    "description": "A reference to an other items sequence_number if a relation exists",
                    "type": "integer"
                },
                "text": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "unit_amount": {
                    "type": "number",
                    "description": "Signed per-unit deposit amount: negative when the deposit is returned to the customer."
                },
                "amount": {
                    "type": "number",
                    "description": "Signed total deposit amount (unit_amount * quantity): negative when the deposit is returned to the customer."
                },
                "quantity": {
                    "type": "integer",
                    "description": "Number of times deposit is applied"
                },
                "tax_percentage": {
                    "type": "number",
                    "description": "Tax on deposit is not always the same as the goods/service connected"
                },
                "sub_deposits": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/sub_deposits_vat"
                    }
                }
            },
            "required": [
                "sequence_number",
                "amount",
                "unit_amount",
                "quantity"
            ],
            "additionalProperties": false
        },
        "price_modifier_element": {
            "title": "Price modifier",
            "description": "A single price modifier, keyed by direction: {\"discount\": {...}} reduces what the customer pays, {\"surcharge\": {...}} increases it. The key carries the direction — there is no action/type field and no sign on amount. Used identically at line and receipt level.",
            "type": "object",
            "minProperties": 1,
            "maxProperties": 1,
            "additionalProperties": false,
            "properties": {
                "discount": {
                    "$ref": "#/$defs/price_modifier"
                },
                "surcharge": {
                    "$ref": "#/$defs/price_modifier"
                }
            }
        },
        "tender_cash": {
            "title": "Cash payment",
            "description": "Cash payment. Carries no additional fields; the enclosing key identifies it.",
            "type": "object",
            "properties": {},
            "additionalProperties": false
        },
        "card_token_element": {
            "title": "Tokenized payment card",
            "description": "Gives a token value of the payment card and tokenizier info/scheme.",
            "type": "object",
            "properties": {
                "value": {
                    "type": "string",
                    "description": "tokenized payment card number"
                },
                "scheme": {
                    "type": "string",
                    "description": "Token scheme, vendor specific. Any unique token provider definition, e.g. payprov_name_findity_dr"
                }
            },
            "required": [
                "value",
                "scheme"
            ],
            "additionalProperties": false
        },
        "text_arr": {
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "tender_creditdebit": {
            "title": "Credit or Debit Card Tender",
            "description": "Credit or debit card payment properties",
            "type": "object",
            "properties": {
                "bank_identification_number": {
                    "type": "string",
                    "description": "ISO 8583 field 56 Payment Account Reference, masked card number",
                    "pattern": "^[A-Za-z0-9*-]{0,99}$"
                },
                "acquiring_institution_id_code": {
                    "type": "string",
                    "description": "ISO 8583 field 32, Acquiring institution identification code",
                    "pattern": "^[0-9]{0,11}$"
                },
                "retrieval_reference_number": {
                    "type": "string",
                    "description": "ISO 8583 field 37, Retrieval Reference Number",
                    "pattern": "^[a-zA-Z0-9]{0,12}$"
                },
                "card_acceptor_id": {
                    "type": "string",
                    "description": "ISO 8583 field 42 Card Acceptor Identification Code",
                    "pattern": "^[a-zA-Z0-9\\-]{0,15}$"
                },
                "card_acceptor_terminal_id": {
                    "type": "string",
                    "description": "ISO 8583 field 41 Card Acceptor Terminal ID. If your terminals do not expose an 8-digit ISO value, pass in the last 8 digits of whatever ID they do give you.",
                    "pattern": "^[a-zA-Z0-9\\-]{8}$"
                },
                "card_acceptor_name": {
                    "type": "string",
                    "description": "ISO 8583 field 43 Card Acceptor Name/Location. Printable ASCII (the ISO 8583 ans charset) plus Unicode letters",
                    "pattern": "^[\\p{L}\\x20-\\x7e]{0,40}$"
                },
                "approval_code": {
                    "type": "string",
                    "description": "ISO 8583 field 38 Approval Code",
                    "pattern": "^[a-zA-Z0-9]{6,}$"
                },
                "card_token": {
                    "description": "Gives a token value of the payment card and tokenizier info/scheme.",
                    "$ref": "#/$defs/card_token_element"
                },
                "payment_slip": {
                    "description": "Payment slip data as an array of texts",
                    "$ref": "#/$defs/text_arr"
                }
            },
            "additionalProperties": false
        },
        "tender_barcode_element": {
            "description": "bar code representation of tender information",
            "type": "object",
            "properties": {
                "value": {
                    "type": "string",
                    "description": "the barcode value"
                },
                "type": {
                    "$ref": "#/$defs/barcode_element",
                    "description": "the barcode type"
                }
            },
            "required": [
                "value",
                "type"
            ],
            "additionalProperties": false
        },
        "tender_giftcard": {
            "title": "Giftcard payment type",
            "description": "Gives giftcard payment info: amount (initial, current), valid period, etc. Dates must be given in format: 2016-09-29",
            "type": "object",
            "properties": {
                "card_number": {
                    "type": "string"
                },
                "date_sold": {
                    "type": "string",
                    "format": "date"
                },
                "date_activated": {
                    "type": "string",
                    "format": "date"
                },
                "expiration_date": {
                    "type": "string",
                    "format": "date"
                },
                "initial_balance": {
                    "type": "number"
                },
                "current_balance": {
                    "description": "Remaining balance on the gift card after the purchase. Omit when unknown.",
                    "type": "number"
                },
                "barcode": {
                    "description": "barcode representation of tender details",
                    "$ref": "#/$defs/tender_barcode_element"
                }
            },
            "required": [
                "card_number"
            ],
            "additionalProperties": false
        },
        "phone_number_id": {
            "title": "phone number identifer",
            "description": "more restrictive international phone number format used as identifier, based on ITU-T E.123",
            "type": "string",
            "pattern": "^\\+(?:[0-9]\\x20?){6,14}[0-9]$"
        },
        "tender_details": {
            "title": "Tender details",
            "description": "Any additional payment information: free-form string key/value pairs, plus an optional barcode representation of the details.",
            "type": "object",
            "minProperties": 1,
            "properties": {
                "barcode": {
                    "description": "barcode representation of tender details",
                    "$ref": "#/$defs/tender_barcode_element"
                }
            },
            "additionalProperties": {
                "type": "string"
            }
        },
        "tender_mobile": {
            "title": "Generic mobile payment type",
            "description": "Gives basic mobile payment information, mobile specific payment info can be added in the tender_details section",
            "type": "object",
            "properties": {
                "provider": {
                    "type": "string",
                    "enum": [
                        "swish:pay"
                    ],
                    "description": "Mobile payment name, e.g. swish, android wallet, etc"
                },
                "phone": {
                    "$ref": "#/$defs/phone_number_id"
                },
                "tender_details": {
                    "description": "any additional payment information needed",
                    "$ref": "#/$defs/tender_details"
                }
            },
            "additionalProperties": false
        },
        "tender_loyalty": {
            "title": "Loyalty payment",
            "description": "Loyalty payment, bonus check.",
            "type": "object",
            "minProperties": 1,
            "properties": {
                "points_redeemed": {
                    "type": "number",
                    "description": "The number of loyalty points redeemed by the customer. Provide this and/or amount_redeemed, depending on how the redemption is denominated."
                },
                "amount_redeemed": {
                    "type": "number",
                    "description": "The amount redeemed by the customer. Provide this and/or points_redeemed, depending on how the redemption is denominated."
                },
                "loyalty_program": {
                    "type": "string",
                    "description": "Add loyalty account data to the customer definitions"
                }
            },
            "additionalProperties": false
        },
        "tender_coupon": {
            "title": "Coupon payment",
            "description": "Coupon payment",
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "coupon name"
                },
                "description": {
                    "type": "string",
                    "description": "Any additional coupon description, if needed"
                },
                "coupon_code": {
                    "type": "string",
                    "description": "Coupon identifier"
                },
                "manufacture_id": {
                    "type": "string",
                    "description": "If a manufacture coupon"
                },
                "family_code": {
                    "type": "string",
                    "description": "Assigned by the manufacture for each product, validates that a consumer has purchased a qualifying product"
                },
                "promotion_code": {
                    "type": "string",
                    "description": "Identifies promotion campaign"
                },
                "coupon_value": {
                    "type": "number",
                    "description": "Coupon value when redeemed"
                },
                "quantity": {
                    "$ref": "#/$defs/quantity_element",
                    "description": "Quantity of items covered by the coupon"
                },
                "expiration_date": {
                    "type": "string",
                    "format": "date"
                },
                "item_links": {
                    "type": "array",
                    "items": {
                        "type": "integer"
                    },
                    "description": "Links to sold item sequence numbers part of promotion is applicable"
                },
                "barcode": {
                    "description": "barcode representation of tender details",
                    "$ref": "#/$defs/tender_barcode_element"
                }
            },
            "required": [
                "coupon_code",
                "coupon_value"
            ],
            "additionalProperties": false
        },
        "tender_generic": {
            "title": "Generic payment type",
            "description": "Generic tender type. type names the specific generic tender; use \"other\" together with type_name when none of the named types matches. Add tender-specific payment info in the details section.",
            "type": "object",
            "properties": {
                "type": {
                    "type": "string",
                    "enum": [
                        "purchase_order",
                        "accounts_receivable",
                        "house_account",
                        "voucher",
                        "other"
                    ],
                    "description": "The specific generic tender type."
                },
                "type_name": {
                    "type": "string",
                    "description": "Free-text name for the tender. Required when type is \"other\"."
                },
                "tender_details": {
                    "description": "any additional payment information needed",
                    "$ref": "#/$defs/tender_details"
                }
            },
            "anyOf": [
                {
                    "title": "Named generic tender",
                    "properties": {
                        "type": {
                            "enum": [
                                "purchase_order",
                                "accounts_receivable",
                                "house_account",
                                "voucher"
                            ]
                        }
                    }
                },
                {
                    "title": "Free-text tender (other + type_name)",
                    "properties": {
                        "type": {
                            "const": "other"
                        }
                    },
                    "required": [
                        "type_name"
                    ]
                }
            ],
            "required": [
                "type"
            ],
            "additionalProperties": false
        },
        "tender_element": {
            "title": "Payment information",
            "description": "One or more tender types can be used. Each type is described and the amount used for each tender type",
            "type": "object",
            "properties": {
                "amount": {
                    "type": "number",
                    "description": "Signed amount for this tender: positive is money from the customer to the merchant, negative is money back to the customer (a refund/change leg)."
                },
                "amount_applied_to_bill": {
                    "type": "number",
                    "description": "the amount applied to the transaction total"
                },
                "foreign_currency_amount": {
                    "$ref": "#/$defs/foreign_currency",
                    "description": "Gives exchange rate etc when payment is done with a foreign currency"
                },
                "rounding": {
                    "type": "number",
                    "description": "If the amount to pay needs rounding"
                },
                "tip": {
                    "description": "Tip included in amount; amount = amount_applied_to_bill + rounding + tip.",
                    "type": "object",
                    "properties": {
                        "amount": {
                            "type": "number"
                        }
                    },
                    "required": [
                        "amount"
                    ],
                    "additionalProperties": false
                },
                "tender": {
                    "type": "object",
                    "description": "The payment/tender type used and its type-specific details, as a single-key object naming the type, e.g. {\"cash\": {...}}. The key implies the type, so it need not be repeated inside the value.",
                    "minProperties": 1,
                    "maxProperties": 1,
                    "additionalProperties": false,
                    "properties": {
                        "cash": {
                            "$ref": "#/$defs/tender_cash"
                        },
                        "creditdebit": {
                            "$ref": "#/$defs/tender_creditdebit"
                        },
                        "giftcard": {
                            "$ref": "#/$defs/tender_giftcard"
                        },
                        "mobile": {
                            "$ref": "#/$defs/tender_mobile"
                        },
                        "loyalty": {
                            "$ref": "#/$defs/tender_loyalty"
                        },
                        "coupon": {
                            "$ref": "#/$defs/tender_coupon"
                        },
                        "generic": {
                            "$ref": "#/$defs/tender_generic"
                        }
                    }
                }
            },
            "required": [
                "amount",
                "tender"
            ],
            "additionalProperties": false
        },
        "customer_loyalty_program": {
            "type": "object",
            "description": "Customer loyalty information",
            "properties": {
                "program": {
                    "type": "string",
                    "description": "Loyalty program name, example: SJ Prio, ICA, SAS Eurobonus, etc. NOTE! Named used must be approved by Findity"
                },
                "level": {
                    "type": "string",
                    "description": "Some programs has different levels based on point etc "
                },
                "customer_number": {
                    "type": "string",
                    "description": "The actual loyalty number"
                },
                "incremental_count": {
                    "type": "integer",
                    "description": "Loyalty points gained/lost in transaction"
                },
                "current_count": {
                    "type": "integer",
                    "description": "Total loyalty points after increment"
                },
                "target_count": {
                    "type": "integer",
                    "description": "Loyalty points needed to achieve next goal/level"
                },
                "effective_date": {
                    "type": "string",
                    "format": "date"
                },
                "expiration_date": {
                    "type": "string",
                    "format": "date"
                }
            },
            "required": [
                "program",
                "customer_number"
            ],
            "additionalProperties": false
        },
        "customer": {
            "type": "object",
            "description": "The customer the receipt belongs to — the customer's identifiers together with descriptive details in a single object. The identifiers under `id` are what Kivra uses to match the receipt to a user's account, so they must be accurate: an incorrect or missing identifier means the receipt cannot be matched and delivered to the right user.",
            "properties": {
                "id": {
                    "type": "object",
                    "description": "Customer identifiers used to match the receipt to a Kivra user. Any combination may be supplied; each value must be accurate, since an incorrect identifier prevents the receipt from reaching the right user.",
                    "minProperties": 1,
                    "properties": {
                        "service_id": {
                            "type": "string",
                            "description": "The digital receipt service customer identifier"
                        },
                        "email": {
                            "type": "string",
                            "format": "email"
                        },
                        "phone": {
                            "$ref": "#/$defs/phone_number_id"
                        },
                        "civic_registration_number": {
                            "type": "string",
                            "pattern": "^[12]{1}[90]{1}[0-9]{6}-?[0-9]{4}$",
                            "description": "swedish personnummer 12 digits"
                        }
                    },
                    "additionalProperties": false
                },
                "name": {
                    "type": "string"
                },
                "contact": {
                    "type": "object",
                    "properties": {
                        "address": {
                            "$ref": "#/$defs/address"
                        }
                    },
                    "additionalProperties": false
                },
                "geo_location": {
                    "$ref": "#/$defs/geo_location"
                },
                "loyalty": {
                    "$ref": "#/$defs/customer_loyalty_program"
                }
            },
            "additionalProperties": false
        },
        "customer_information": {
            "type": "object",
            "description": "Defines customer information, like name, address, loyalty program.",
            "properties": {
                "name": {
                    "type": "string"
                },
                "contact": {
                    "type": "object",
                    "properties": {
                        "address": {
                            "$ref": "#/$defs/address"
                        },
                        "email": {
                            "type": "string",
                            "format": "email"
                        },
                        "phone": {
                            "$ref": "#/$defs/phone_number"
                        }
                    },
                    "additionalProperties": false
                },
                "geo_location": {
                    "$ref": "#/$defs/geo_location"
                },
                "loyalty": {
                    "$ref": "#/$defs/customer_loyalty_program"
                }
            },
            "additionalProperties": false
        },
        "customer_order_information": {
            "type": "object",
            "description": "Use this if the receipt is connected to an order or booking.",
            "minProperties": 1,
            "properties": {
                "order_number": {
                    "type": "string",
                    "description": "Order/booking number connected to the receipt. Provide this for a new order/booking; for an existing order/booking being changed, use order_reference instead."
                },
                "order_reference": {
                    "type": "string",
                    "description": "Order/booking number connected to the receipt for an existing order/booking when the order is changed. For a new order/booking, use order_number instead."
                },
                "customer": {
                    "$ref": "#/$defs/customer_information",
                    "description": "To whom the order/order_reference belongs"
                }
            },
            "additionalProperties": false
        }
    }
}