Concepts
Amounts as decimal strings
Why the gateway sends and receives money as decimal strings (MoneyCOP), which types each SDK accepts when sending an amount, and how to read amounts from responses without losing precision.
On this page
In the contract, every amount is a decimal string: the
MoneyCOP schema ("3500000", "467009.88", "53500.00"). Never
a floating-point number.
{ "amount": "467009.88", "currency": "COP" }The reason is simple: 0.1 + 0.2 isn’t 0.3 in binary. A float can turn 467009.88 into
467009.87999999995 somewhere along the way (your ORM, your JSON serializer, a
spreadsheet), and with money a one-cent difference breaks a reconciliation. A string travels exactly from
end to end.
Sending amounts #
Each SDK normalizes whatever you pass it into the same string the Python SDK would send:
| SDK | Accepted types | Recommended |
|---|---|---|
| Python | str, int, Decimal | Decimal("467009.88") or "467009.88" |
| JavaScript / TS | string, number, bigint | string for money you didn’t calculate yourself |
| PHP | string, int, decimal Stringable objects (e.g. brick/math BigDecimal); float is accepted but discouraged | string |
| .NET | Amount, with implicit conversion from string, int, long, decimal (and double, discouraged) | decimal or string |
| Go | compense.Amount (string constant), AmountFromInt, AmountFromRat, AmountFromFloat (discouraged) | "467009.88" or AmountFromInt |
from decimal import Decimal
client.loans.register_payment("CRD-00123", amount=Decimal("467009.88"),
reference="REC-2026-001", channel="CASH")
client.wallet.topups.create(document="1032456789", phone_number="3001234567",
carrier="CLARO", amount=20000) # int works tooawait client.loans.registerPayment("CRD-00123", { amount: "467009.88", reference: "REC-2026-001", channel: "CASH" });
await client.wallet.topups.create({ document: "1032456789", phoneNumber: "3001234567",
carrier: "CLARO", amount: 20000 }); // integer number: safe
$client->loans->registerPayment('CRD-00123', amount: '467009.88', reference: 'REC-2026-001', channel: 'CASH');
$client->wallet->topups->create(document: '1032456789', phoneNumber: '3001234567',
carrier: 'CLARO', amount: 20000);await client.Loans.RegisterPaymentAsync("CRD-00123", 467009.88m, "REC-2026-001", channel: "CASH");
await client.Wallet.Topups.CreateAsync("1032456789", "3001234567", "CLARO", 20000);client.Loans.RegisterPayment(ctx, "CRD-00123", &compense.LoanPaymentParams{
Amount: "467009.88", Reference: "REC-2026-001", Channel: "CASH",
})
client.Wallet.Topups.Create(ctx, &compense.TopupParams{
Document: "1032456789", PhoneNumber: "3001234567", Carrier: "CLARO",
Amount: compense.AmountFromInt(20000),
})# In JSON, the amount goes in quotes:
-d '{"amount":"467009.88","reference":"REC-2026-001","channel":"CASH"}'Reading amounts #
Responses also carry amounts as strings. The typed models expose them as Money
(amount as a string + currency), for example the balance:
from decimal import Decimal
balance = client.wallet.balance("1032456789")
available = Decimal(balance.available.amount) # never float(...)
print(available, balance.available.currency)const balance = await client.wallet.balance("1032456789");
console.log(balance.available.amount, balance.available.currency); // string: use it with a decimal library
$balance = $client->wallet->balance('1032456789');
echo $balance->available->amount, ' ', $balance->available->currency, PHP_EOL; // use bcmath or brick/math
Balance balance = await client.Wallet.BalanceAsync("1032456789");
decimal available = decimal.Parse(balance.Available.Amount, CultureInfo.InvariantCulture);balance, err := client.Wallet.Balance(ctx, "1032456789")
if err != nil {
log.Fatal(err)
}
r, _ := new(big.Rat).SetString(balance.Available.Amount) // exact
fmt.Println(r.FloatString(2), balance.Available.Currency)curl -s "https://sandbox.dev.compense.co/gw/v1/gateway/wallet/balance/?document=1032456789" \
-H "X-API-Key: $COMPENSE_API_KEY" | jq -r '.available_cash'In bodies without a model (dict, JsonObject, array, map[string]any) amounts arrive as
the engine’s string. In Go, the SDK decodes with json.Number, so the engine’s numbers
keep their exact digits (v.(json.Number).String()).
Some sandbox responses contain numbers
A few sandbox bodies (simulators, monetary allowance) return amounts as JSON numbers
(50000.0). Write your code to accept both and always convert to decimal, never to float.
Currency #
The default currency is COP and amounts are expressed in pesos (not cents). Foreign
exchange operations (FX) carry the currency explicitly (sell_currency,
buy_currency).