Token units in the Simply Tokenized API are expressed in the smallest unit — an integer string with no decimal point. The number of decimal places comes from the offering’s decimals field.
Quick rule
To order 10 tokens on an offering with decimals: 8:
Send "units": "10000000000" — not "10" or "10.0".
Always read decimals from the offering before creating an order or interpreting units, balance, or transaction amounts. Decimals can differ per offering.
Fields
| Field | Type | Where it appears | Meaning |
|---|
decimals | number | Offering, order offering, wallet balance, transaction | Number of fractional digits for the token (e.g. 8) |
units | string | Create order (request), orders (response), transactions (response), webhooks | Token amount in smallest unit |
balance | string | Wallet balances | Wallet balance in smallest unit |
Currency amounts such as total_amount, paid_amount, and webhook amount are not smallest-unit values — they are normal currency numbers.
Conversion
Human amount → API units
units = human_amount × 10^decimals
| Human amount | decimals | units to send |
|---|
| 1 token | 8 | "100000000" |
| 5 tokens | 8 | "500000000" |
| 10 tokens | 8 | "10000000000" |
| 987 tokens | 8 | "98700000000" |
| 1.5 tokens | 8 | "150000000" |
API units → human amount
human_amount = units ÷ 10^decimals
Example: "500000000" with decimals: 8 → 5 tokens.
Create order example
First, get the offering and note its decimals:
curl "https://dev.go.simplytokenized.com/_api/offerings/{offeringId}?lang=en" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
If the offering has decimals: 8 and you want to order 10 tokens:
curl -X POST "https://dev.go.simplytokenized.com/_api/offerings/{offeringId}/orders" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: order-create-abc123" \
-d '{
"account_id": "dabc6029-db0e-422e-a151-007cda958bf6",
"units": "10000000000"
}'
Code examples
function toUnits(humanAmount, decimals) {
const [whole, fraction = ""] = String(humanAmount).split(".");
const paddedFraction = fraction.padEnd(decimals, "0").slice(0, decimals);
return `${whole}${paddedFraction}`.replace(/^0+/, "") || "0";
}
// 10 tokens with 8 decimals
toUnits("10", 8); // "10000000000"
function fromUnits(units, decimals) {
const value = units.padStart(decimals + 1, "0");
const whole = value.slice(0, -decimals) || "0";
const fraction = value.slice(-decimals).replace(/0+$/, "");
return fraction ? `${whole}.${fraction}` : whole;
}
fromUnits("500000000", 8); // "5"
from decimal import Decimal
def to_units(human_amount: str, decimals: int) -> str:
amount = Decimal(human_amount)
factor = Decimal(10) ** decimals
return str(int(amount * factor))
# 10 tokens with 8 decimals
to_units("10", 8) # "10000000000"
def from_units(units: str, decimals: int) -> str:
amount = Decimal(units) / (Decimal(10) ** decimals)
return format(amount.normalize(), "f")
from_units("500000000", 8) # "5"
Where this applies
| API | Field | Direction |
|---|
| Create order | units | Request — send smallest unit |
| List offering orders | units | Response |
| Get offering order | units | Response |
| List account orders | units | Response |
| Get wallet balances | balance | Response |
| List transactions | units | Response |
| Webhook events | units | Event payload |
Common mistakes
| Mistake | Result |
|---|
Sending "units": "10" when decimals is 8 | Orders 0.00000010 tokens instead of 10 |
Using a float like 10000000000.0 | Validation error — units must be a string |
| Assuming all offerings use 8 decimals | Wrong amount — always read decimals from the offering |
Confusing units with total_amount | total_amount is currency (e.g. USD), not token smallest unit |