Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define money amounts in an API

Tags:

I'm going to create an API which contains money amounts. I was wondering what the best practices are, or whether someone has some good or bad experiences with certain formats.

  • should we transmit base units or minor units? (amount vs amount_cents)
  • should we represent the numbers as integers / decimals or as strings?

I've seen the following two possibilities:

  1. send amounts as a string like so: "5.85" (a string with base units)
  2. send amounts in their minor unit: 585 (an integer which expresses the amount in the minor unit)

I'm going back and forth between those two. So I went out to check what other APIs use and came up with the following list:

  • Stripe: integer with minor units
  • Braintree: string with base units
  • Google Wallet: string with base units
  • Paypal: string with base units
  • Amazon Payments: string with base units
  • The Currency Cloud: string with base units
  • 2checkout: string with base units
  • Adyen: integer with minor units
  • Dwolla: decimal with base units
  • GotoBilling: weird heuristics! "Amount may be formatted with or without a decimal. If no decimal is given two (2) decimal places are assumed (1.00 = 100)"
  • GoCardless: string with base units
  • Intuit: decimal with base units in requests, string with base units in responses
  • Klarna: integer with minor units
  • MasterCard: integer with minor units
  • Paynova: string with base units
  • Rogers Catalyst: string with base units
  • WePay: string with base units
  • Venmo: decimal with base units

So, out of 18 sampled APIs, 4 are using minor units, 13 are using base units and 1 is using a hard-to-comprehend mixture. And within the 13 who use base units, 10 are transmitting them as quoted strings, 3 as unquoted decimals (actually 2 and a half if you look at Intuit).

I personally feel uncomfortable having to parse a string like "8.20", because if you parse this it becomes "8.19999999..." if you make the mistake to use floats. So I'm leaning towards sending integers only. But I don't think this is a great argument, and I see that generally APIs tend to go with base units as strings.

Do you have any good arguments for/against each format?

like image 313
alvi Avatar asked Mar 30 '15 08:03

alvi


People also ask

What is “currency and money” api?

The goals of “Currency and Money” API: 1 To provide an API for handling and calculating monetary amounts 2 To define classes representing currencies and monetary amounts, as well as monetary rounding 3 To deal with currency exchange rates 4 To deal with formatting and parsing of currencies and monetary amounts More ...

What is the use case for a currency conversion API?

Currency conversion is an important aspect of dealing with money. Unfortunately, these conversions have a great variety of different implementations and use cases. The API focuses on the common aspects of currency conversion based on the source, target currency, and exchange rate.

What is a monetary amount?

It's always associated with CurrencyUnit and defines a monetary representation of a currency. The amount can be implemented in different ways, focusing on the behavior of a monetary representation requirements, defined by each concrete use cases. For example. Money and FastMoney are implementations of the MonetaryAmount interface.

How to represent the amount of money in JSON?

Amount of money should be represented as string. The idea of using string is that any client that consumes the json should parse it into decimal type such as BigDecimal to avoid floating point imprecision. However it would only be meaningful if any part of the system avoids floating point too.


1 Answers

Integers will eat the dot, that's one less byte :D Integers will have a max_int, do you have anyone rich enough that may overflow?

People that will parse a currency string as float will turn the int to float anyway.

If you send binary data, integer will be much smaller than a string and the way to go. If you send xml anyway, you might as well define it a string (the file is probably compressed before sending right?), try to make it "currency" type as opposed to listing it as a full string though.

like image 55
gia Avatar answered Sep 22 '22 11:09

gia