Amounts and currency 💱

Almost every monetary field in the Cardda API is an integer in the minor unit of its own currency. There is no single "cents" rule across the API, because the minor unit is not always a hundredth. (A handful of fields serialize the minor-unit value as a string, and a couple of fields report whole currency units instead — both are listed under Reading amounts back.)

🚧

CLP has no subunit — the minor unit IS the peso.

To transfer $1.000 CLP you send 1000, not 100000. A field named *_cents on a CLP amount still holds whole pesos: the suffix is a naming convention inherited from the Money library, not a statement about the unit.

The rule

For a field holding an amount in currency C, the integer you send (and receive) is:

integer_value = decimal_amount × subunit_to_unit(C)
CurrencyMinor unitsubunit_to_unit1000 meansTo send 1.000 units, send
CLP (Chilean peso)the peso itself1$1.0001000
USDcent100US$10.00100000
MXN (Mexican peso)centavo100$10.00 MXN100000
PEN (Peruvian sol)céntimo100S/ 10.00100000
CLF (UF, Unidad de Fomento)ten-thousandth100000.1 UF10000000

CLP and CLF are the two that break the "divide by 100" habit — CLP because it has no subunit at all, CLF (UF) because it carries four decimals.

How to know which currency a field is in

Always read the currency off the record, never off the field name:

SurfaceCurrency comes from
bank_transactions.amountthe sending account's country/provider — CLP for Chilean banks and the Cardda wallet, MXN for STP, PEN for BCP
purchase_orders.amount_centsthe sibling currency field on the same purchase order (CLP, CLF/UF, or USD)
vendor_cards.*_centsthe card's limit_currency
card_transactions.amount_centsthe sibling currency (merchant currency); target_amount_cents uses target_currency
budgets.*_cents, bills.amountCLP (v1 is CLP-only)
Accounting transactionsthe sibling currency / target_currency

Worked examples

# Transfer $1.000 CLP from a Chilean bank account
curl -X POST 'https://api.cardda.com/v1/banking/bank_transactions' \
  -H 'company-id: <company_uuid>' -H 'Authorization: <token>' \
  -H 'Content-Type: application/json' \
  -d '{"sender_id":"<clp_account_uuid>","recipient_id":"<recipient_uuid>",
       "amount":1000,"description":"Pago servicios"}'
# amount 1000 == $1.000 CLP.  Sending 100000 would transfer $100.000.

# A purchase order for 40 UF
# currency CLF, minor unit = 1/10.000 UF  →  40 × 10000
# `UF` is accepted on write too and is normalized to the ISO 4217 code `CLF` on save,
# so `CLF` is what reads back and what filters match.
{"currency": "CLF", "amount_cents": 400000}

# A purchase order for US$ 990
# currency USD, minor unit = cent  →  990 × 100
{"currency": "USD", "amount_cents": 99000}

Reading amounts back

Response fields follow the same rule, with two exceptions worth knowing:

  • Accounting (/v1/accounting/transactions) serializes monetary values as strings of integer minor units, to preserve precision (Money runs with default_infinite_precision, so the value is a BigDecimal rendered as a JSON string).
  • A few card fields are decimal strings in whole currency units, not minor unitsremaining_balance and preference_restricted_spendable on vendor_cards are documented as such on their schema. When a field's description says "as a decimal string in the card currency (not cents)", believe the description over the naming pattern.

Related

  • How to filter results — filtering on amount fields uses the same integer values.
  • Errors — how validation failures on amounts are reported.

Did this page help you?