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

# Money and currency

> How amounts, currencies and money limits work in the VEXiON cards API: minor units, the business currency, the largest bill and cashback limits.

Every money field in this API is a whole number in **minor units**, and every business has **one currency**. This page lists the rules and the limits.

## Currencies

A business uses one of 8 currencies.

| Code | Currency | Example amount | In the API |
| - | - | - | - |
| `EUR` | Euro | 12.50 EUR | `1250` |
| `CZK` | Czech koruna | 250 CZK | `25000` |
| `GBP` | Pound sterling | 8.99 GBP | `899` |
| `HUF` | Hungarian forint | 1 990 HUF | `199000` |
| `PLN` | Polish zloty | 24.90 PLN | `2490` |
| `RON` | Romanian leu | 39.90 RON | `3990` |
| `CHF` | Swiss franc | 15 CHF | `1500` |
| `USD` | US dollar | 4.75 USD | `475` |

All 8 use 2 decimals in this API, also HUF. A bill of 1 990 Ft is `amount_minor: 199000`. Money fields end in `_minor`. The `Invoice` resource is the one exception: it shows amounts in major units.

## One currency per business

* The currency of a business is `default_currency` on `GET /v1/organization`. It is also the `currency` on every card and every customer card slot.
* It is set from the country of the first location.
* It is locked after the first transaction, customer balance or gift card purchase. To change it after that, contact support.
* Your VEXiON subscription is always billed in EUR. That does not depend on the business currency. Invoices from `GET /v1/invoices` are in EUR.

## Send `currency` or leave it out

On `POST /v1/transactions`, `currency` is optional. When you send it, it must be the business currency, in any letter case (`czk` works for a CZK business).

Any other code answers `422 currency_mismatch`. A code we do not support answers the same. `field_errors[0].expected_currency` tells you which currency to send.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "currency_mismatch",
    "message": "currency EUR does not match the business currency CZK. Send CZK or omit the field.",
    "param": "currency",
    "field_errors": [
      { "param": "currency", "code": "currency_mismatch", "message": "Expected CZK.", "expected_currency": "CZK" }
    ]
  }
}
```

The same check runs on a coupon redeem. The MCP tool `create_transaction` follows the same rule.

## Largest single bill

`amount_minor` on `POST /v1/transactions` has a limit per currency. It is about 10,000 EUR worth. Above it the request answers `422 amount_too_large` with `param` `amount_minor`.

| Currency | Largest bill (major units) | Largest `amount_minor` |
| - | - | - |
| `EUR` | 10,000 | `1000000` |
| `CZK` | 250,000 | `25000000` |
| `HUF` | 4,000,000 | `400000000` |
| `PLN` | 45,000 | `4500000` |
| `RON` | 50,000 | `5000000` |
| `GBP` | 9,000 | `900000` |
| `CHF` | 10,000 | `1000000` |
| `USD` | 11,000 | `1100000` |

The business can set a lower **Maximum transaction amount** in the dashboard under **Settings**, **General**. It applies on the API and on the MCP server as well. A bill above it answers the same `422 amount_too_large`.

A `redeem` carries no bill. `amount_minor` on a redeem, also on a coupon redeem, answers `422 amount_not_valid_for_action`.

## Largest `value`

An explicit `value` has a limit per call. Above it the request answers `422 value_too_large` with `param` `value`.

| Card | Largest `value` |
| - | - |
| Points card | 100,000 points |
| Cashback card | Points worth no more than the largest bill of the currency: `value` x `cashback_point_value`. With a point value of 0.01 on a EUR card that is 1,000,000 points. |
| Stamp card, `award` | One full card (`stamps_required`) |

An `amount_minor` award is checked as a bill, not as a `value`.

`initial_state.points` on `POST /v1/customers` follows the starting bonus limit of the card. Above it the request answers `422 validation_failed` with `field_errors[].code` `out_of_range`.

## Retries with `external_id`

Send an `external_id` so a retry cannot book the same event twice. A retry of the same transaction returns the original with `201`.

When a retry sends `amount_minor` or `currency`, they must match what was booked. A different `action`, `value`, `amount_minor` or `currency` under the same `external_id` answers `409 external_id_conflict`. A field you leave out is not compared.

## Cashback limits

A cashback card pays back a percent of the bill:

`earn_rate_per_unit` x `cashback_point_value` x 100, times the level multiplier on a card with levels.

| Card | Largest cashback |
| - | - |
| Without levels | 30 percent |
| With levels | 60 percent per level |

`cashback_point_value` must be above 0. On a card connected to Oberon, or to Papaya with the card basis, the point value of the till counts for the limit.

Above the limit the request answers `422 validation_failed` with `field_errors[].code` `out_of_range`. The `param` is `mechanics.earn_rate_per_unit`, `mechanics.cashback_point_value` or `mechanics.tiers`, whichever you changed.

On `PATCH` only a changed value is checked. A card that already pays more keeps saving other fields.

## Reward limits

| Rule | Limit |
| - | - |
| Rewards on one card | At most 20 |
| `points_required` | At least 1 |
| `value` (fixed amount off) | A whole number of minor units, at least 1. It reads back for every currency. |
| `percentage` (percent off) | A whole number from 1 to 99 |
| Free product | A reward with neither `value` nor `percentage` |

Send `value` or `percentage` on a reward, not both. A reward that you read from the API and send back unchanged in a `PATCH`, with its `id` and without `value` or `percentage`, keeps the stored reward.

## Rounding

* Points from a bill are `amount_minor / 100 x earn_rate_per_unit x level multiplier`, rounded once at the end to the nearest whole point. Halves round up.

## Dashboard scanner

The scanner in the dashboard has its own checks:

* A bill above the largest bill of the currency is refused.
* A bill above 1,000 EUR worth opens a **Large amount** question that the staff member confirms: 1,000 EUR, 25,000 CZK, 400,000 HUF, 4,500 PLN, 5,000 RON, 900 GBP, 1,000 CHF or 1,100 USD.

See [Errors](https://vexioncards.mintlify.site/api-reference/errors.md) for every code and the [Changelog](https://vexioncards.mintlify.site/api-reference/changelog.md) for what changed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.