Difference Between IRR and Toman: A Developer’s Guide to Units and Formatting
The difference between IRR and Toman for developers: 1 Toman = 10 Rial, storing amounts, formatting Persian numbers, parsing input and avoiding 10× bugs.

- The Rial (IRR) is Iran’s legal currency unit; the Toman equals 10 Rial and is what people use day to day. There is no ISO code for Toman.
- Store integer amounts with an explicit unit column, convert once at the boundary and format only for display.
- Persian digits, thousands separators and a possible redenomination are the other traps to design for.
Ask ten Iranian users how much something costs and all ten will answer in Toman. Look at their bank card receipt and it says Rial. That everyday ambiguity becomes a real bug the moment it enters a database. This guide explains the difference between IRR and Toman from a developer’s point of view and gives concrete patterns for storage, conversion, input and display.
quote=IRT or quote=IRR instead of multiplying yourself.Part of the Iranian Rial exchange rate API guide.
The basics
| Rial | Toman | |
|---|---|---|
| Code | IRR (ISO 4217) | None; “IRT” used informally |
| Value | 1 | 10 Rial |
| Where used | Bank systems, cheques, official documents, card terminals | Speech, shops, most price lists and websites |
| Minor units | Effectively none in practice | None |
Inflation means everyday amounts run into millions of Toman, so integers are large but still fit easily in a 64-bit integer.
Storage: integer plus unit
CREATE TABLE prices (
id bigserial PRIMARY KEY,
amount bigint NOT NULL, -- integer, no floats
unit varchar(4) NOT NULL CHECK (unit IN ('IRR', 'IRT')),
rate_source varchar(32) NOT NULL, -- e.g. ezrate:tehran
rate_at timestamptz NOT NULL
);- Pick one internal unit (Rial is the safer choice for anything that touches banks) and convert at the edges.
- Never use floating point for money. For non-integer values such as crypto, use
numeric/Decimal. - Keep the rate and its timestamp next to any converted amount, so you can explain it later.
Conversion in one place
export type Unit = "IRR" | "IRT";
export function toRial(amount: bigint, unit: Unit): bigint {
return unit === "IRR" ? amount : amount * 10n;
}
export function fromRial(rial: bigint, unit: Unit): bigint {
if (unit === "IRR") return rial;
if (rial % 10n !== 0n) throw new Error("Rial amount is not a whole number of Toman");
return rial / 10n;
}A single, tested function prevents the classic “multiplied by ten twice” bug that happens when two layers each assume the other did not convert.
Getting rates in the unit you need
# Toman (default)
curl -H "X-API-Key: $EZRATE_KEY" "https://api.ezrate.me/v1/rates/usd"
# Rial
curl -H "X-API-Key: $EZRATE_KEY" "https://api.ezrate.me/v1/rates/usd?quote=IRR"
# convert an amount from Toman to Rial-free units, e.g. 2,000,000 Toman in USD
curl -H "X-API-Key: $EZRATE_KEY" "https://api.ezrate.me/v1/convert?from=irt&to=usd&amount=2000000&side=sell"The response always includes quote in meta (and per rate), so you can assert the unit in code. See the JSON reference.
Formatting for display
const fa = new Intl.NumberFormat("fa-IR"); // ۱۲۳٬۴۵۶
const en = new Intl.NumberFormat("en-US"); // 123,456
function price(amount, unit, locale = "fa") {
const n = (locale === "fa" ? fa : en).format(amount);
const label = locale === "fa" ? (unit === "IRT" ? "تومان" : "ریال") : (unit === "IRT" ? "Toman" : "Rial");
return `${n} ${label}`;
}- Persian locale uses Persian digits and the Arabic thousands separator (٬).
- In right-to-left layouts, wrap numbers in an element with
dir="ltr"or useunicode-bidi: isolateto stop the minus sign and separators from jumping. - Large amounts read better as “12.5 million Toman” in headings; keep the full number in tables.

User input
- Accept Persian, Arabic and Latin digits; normalise to Latin before parsing.
- Strip separators (
,,٬, spaces) before parsing. - Show the unit inside the input (“Toman”) and a live preview in words.
- Reject amounts that are not a whole number of Toman if you store Rial and accept Toman.
const digits = { "۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9",
"٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9" };
export const parseAmount = (s) =>
BigInt(s.replace(/[۰-۹٠-٩]/g, d => digits[d]).replace(/[,\s٬]/g, ""));Redenomination
Iran has had plans to introduce a new unit by removing zeros from the Rial. If and when such a change takes effect, there will be a transition period where old and new units coexist. Designing with an explicit unit column today makes that migration a data transformation instead of a rewrite. Track official central-bank announcements for timing.
US Dollar271,860Toman+0.70%
Finally, write the unit into your API contracts and logs as well: a field called amount without a unit is a future bug, while amount_irr or an {amount, unit} object documents itself and lets reviewers spot mistakes immediately.
Related live rates: US dollar rate, 18K gold price, Emami coin price.

Comments (0)
Comments are shown after review. Sign-in is needed to send.


