Skip to content
This is a new version of the Kivra Developer Docs. Report issues or share feedback at avsandare.support@kivra.se. The previous version can be found here.

Receipt validation logic

The Receipt API validates every receipt against the retail JSON schema. It can also check whether the receipt is internally consistent, including totals, line-item calculations, and the information needed to deliver the receipt to a customer.

JSON-schema validation is always enabled. A malformed request is rejected with HTTP 400 and error code 40000.

Semantic validation feedback is opt-in:

  • Newly created sandbox partners are opted in automatically. Ask Kivra to opt out if your data is not ready for these checks.
  • Production partners are opted out until validation feedback is enabled for their account.

When semantic validation feedback is enabled, an error finding rejects the receipt with HTTP 400 and error code 40020. Accepted receipts return HTTP 201 or 202 and can include non-fatal warning and info findings.

Each finding contains:

Field Description
code Stable identifier for the validation check, such as items.paid_mismatch.
severity error, warning, or info.
path Path to the relevant value in the receipt, such as payments[0].tender.card_token.
message Human-readable explanation of the finding.
expected Expected value, when the finding is a mismatch.
actual Value found, when the finding is a mismatch.

Severity describes whether the receipt violates a contract. It does not describe how important the finding is to your integration. Some warning and info findings can be functionally required for a particular flow.

For example, Kivra can deliver a receipt to a customer only when the receipt contains an identifier such as an SSN, email address, phone number, or card_token. A store that does not capture customer identity at checkout typically relies on card_token. Use the par scheme when available for more reliable matching. The related transaction.* findings may be info or warning, but they are effectively required for delivery in this flow.

Examples of validation messages:

Severity Code Example message
error totals.paid_mismatch Paid total 90.00 does not match the sum of payments 100.00 (difference -10.0000).
warning items.amount_math_imprecise extended_amount 36.1500 differs from actual_sales_unit_price x quantity (21.9000 x 1.6500 = 36.1350, difference 0.0150).
info transaction.field_missing card_token is missing on a creditdebit payment; Kivra uses it to match the receipt to a customer.
info transaction.card_token_scheme_not_par The card_token scheme is kivra; par is recommended for reliable matching.

The following codes describe the current validation checks. Their default severities can change over time, so branch on the returned severity instead of assuming a severity for a particular code.

Code Severity Meaning
totals.gross_missing error No gross entry exists in totals.
totals.gross_mismatch error The gross total does not match the sum of item gross amounts.
totals.paid_missing error No paid entry exists in totals.
totals.paid_mismatch error The paid total does not match the sum of payments.
Code Severity Meaning
vat.total_missing error No vat entry exists in totals.
vat.total_mismatch error The vat total does not match the VAT derived from the receipt.
vat.subtotal_inconsistent error The vat total does not match the sum of its sub_totals.
Code Severity Meaning
payments.refund_flag_mismatch error A refund flag is inconsistent with the signed amounts.
amounts.negative error A negative amount appears where only non-negative values are allowed.
Code Severity Meaning
items.amount_math_mismatch error extended_amount does not match actual_sales_unit_price x quantity.
items.amount_math_imprecise warning extended_amount differs from the price-by-quantity result by a small, rounding-level amount.
items.paid_mismatch error The paid total does not match the amount derived from the line items.
items.vat_mismatch error The vat total does not match the VAT derived from the line items.
items.deposit_vat_unresolved warning A deposit’s VAT cannot be derived because it has no tax_percentage and no resolvable item_link.
items.multiple_replace warning A line has more than one replace retail price modifier. replace substitutes the line amount, so at most one is meaningful.
items.incomplete warning A required field is missing on an item.

These checks apply to creditdebit payments.

Code Severity Meaning
transaction.field_missing info A contract-optional creditdebit field is missing, such as card_token or card_acceptor_id. Kivra uses card_token to match the receipt to a customer.
transaction.recommended_field_missing warning A recommended creditdebit field is missing.
transaction.card_token_scheme_not_par info The card_token scheme is not par. The par scheme is recommended for reliable matching.
transaction.payment_slip_missing warning A creditdebit payment has no payment_slip.
Code Severity Meaning
merchant.incomplete warning The merchant or business unit is missing recommended fields.
identifier.incomplete warning The receipt identifier is missing recommended fields.
control_unit.incomplete warning Control unit information is missing recommended fields.

Treat error findings as rejected data and correct the receipt before resending it. Review warning and info findings as well: they can identify missing customer identifiers, incomplete payment data, or presentation issues.

The Merchant Toolbox uses the same receipt rules. Use it to validate a payload and preview how the receipt will render before sending it from your POS integration.