> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chift.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# Amounts, roundings and totals

> How to read e-commerce order amounts, round them consistently, and keep your totals coherent when pushing sales into an accounting system.

## Amounts, roundings and totals

When you push e-commerce sales into an accounting system, the numbers must match to the cent. The sum of your revenue lines, fees, and VAT must equal the order total, and the resulting entry must balance. This guide explains how the Unified API exposes e-commerce order amounts, and the method we recommend to keep them correct once booked.

The sections below cover the [decimal precision](#1-decimal-precision) of the amounts you receive, the [rounding rule](#2-rounding-rule) to apply, how to [handle VAT](#3-handle-vat-per-rate), how to [split a global discount](#4-splitting-a-global-discount), the e-commerce‑specific points on [fees and refunds](#5-fees-and-refunds), and the final [reconciliation](#6-reconcile-and-balance) check.

<Info>
  This guide describes the recommended method, not a constraint the API enforces. When you consume the e-commerce Unified API and write the result into accounting yourself, you are responsible for rounding. If you post through Chift's accounting Unified API, see also [Invoice amounts validation](/guides/by-api/accounting/guides-and-behaviours/invoice-amounts-validation).
</Info>

***

### 🔢 1. Decimal precision

The API response may return e-commerce amounts with **more than 2 decimals**. For example, `unit_price` and `untaxed_amount` can carry up to 4 decimals. The API frequently derives net amounts from a gross total or a discount, and it keeps that finer precision.

<Info>
  Treat every monetary value from the API as raw input. Do not assume it is already at 2 decimals. Do not compare two amounts for equality before you round both.
</Info>

***

### 🧮 2. Rounding rule

Apply a single, consistent rounding rule to every amount **before** you book it:

**2 decimals**, **round half up**.

Examples:

* an `untaxed_amount` of `19.6694` becomes `19.67`
* a computed net of `2.5950413…` becomes `2.60`

<Info>
  Avoid "banker's rounding" (round half to even), which is the default in some languages and libraries. It drifts from amounts that use standard commercial rounding.
</Info>

***

### 🧾 3. Handle VAT per rate

**Reuse the tax amounts the API provides. Do not recompute them.** Each line (`lines`) and each fee (`other_fees`) exposes its own `untaxed_amount`, `tax_amount`, `total`, `tax_rate`, and `tax_id`. This avoids a rounding error that the source system does not have. At order level, you also have `untaxed_amount`, `tax_amount`, and `total`.

If you must derive VAT from a gross (tax‑inclusive) amount and a rate, use the **remainder method** so that net + VAT always equals the exact gross:

```text theme={null}
net = round_half_up(gross / (1 + tax_rate / 100), 2)
vat = gross - net
```

Example: `gross = 3.14`, `tax_rate = 21`

* `net = round(3.14 / 1.21, 2) = 2.60`
* `vat = 3.14 − 2.60 = 0.54`.

Always **reason per VAT rate** (and, if you map revenue to several accounts, per account × rate). Group your lines by `tax_rate` before you compute net and VAT. Never compute on a single global total, which would hide compensating rounding differences between rates. Note that the API returns `tax_rate` rounded to 2 decimals (for example, `21.0`).

***

### ➗ 4. Splitting a global discount

The order exposes `discount_amount` at order level. Line and fee discounts appear in each element's `discounts` array. When a discount applies to the whole order rather than to a single line, spread it across the VAT rates **pro rata** of each rate's base. To avoid a missing cent, give the **remainder to the last bucket** rather than round it separately:

```text theme={null}
for each rate except the last:
    share = round_half_up(global_discount * base_rate / base_total, 2)
    allocated += share
last rate:
    share = global_discount - allocated
```

This guarantees that the sum of the per‑rate discount shares equals the global discount exactly.

***

### 📦 5. Fees and refunds

Three e-commerce‑specific points determine whether your revenue matches the order total:

* **Include fees.** Each `other_fees` entry (for example, shipping) has its own `tax_rate` / `tax_id` and base, and belongs to the order total. Book them per rate, like any revenue line. The `total_without_fees` / `untaxed_amount_without_fees` fields let you separate goods from fees when needed.
* **`total` excludes refunds and returns.** The `total`, `tax_amount`, and `untaxed_amount` fields hold the order **before** refunds and returns. The `current_total`, `current_tax_amount`, and `current_untaxed_amount` fields hold the amounts **after** returns and removals. Use the set that matches what you intend to book. Do not mix the two.
* **Treat refunds separately.** `refunded_amount`, `detailed_refunds`, and `returns` describe money given back. Book refunds as their own entry (or as reverse lines) per VAT rate. Never net a refund inside the original sale's VAT base.

<Note>
  The net (HT) of a line is `untaxed_amount`, or equivalently `total − tax_amount` once you round both to 2 decimals. Pick one convention and apply it consistently across all lines.
</Note>

***

### ✅ 6. Reconcile and balance

After you round each amount per rate to 2 decimals separately, a residual difference of **a few cents** can remain between the sum of your booked lines (net + VAT) and the order `total`. Book that residue on a **rounding account** so the entry balances (debit = credit):

* a **gain** account for a positive difference (for example, `758`);
* a **loss** account for a negative difference (for example, `658`).

<Note>
  A residue of a **cent or two** is normal rounding and belongs on the rounding account. A difference **larger than \~1 €** is not a rounding issue — it signals inconsistent source data (or the wrong `total` vs `current_total` set). Stop and investigate rather than absorb it.
</Note>

***

## In short

Round every amount to 2 decimals half‑up, reuse the VAT the API provides, reason per rate, split global discounts with the remainder on the last bucket, include fees and keep refunds/returns separate (watch `total` vs `current_total`), and close each entry with a reconciliation that sends any residual cent to a rounding account. This is what keeps your accounting totals equal to the original e-commerce amounts.
