Skip to main content
Every money figure in the API has a field in one shape, the money value:
All four members are always present. A figure the platform does not know is absent, never { "value": 0 } and never an empty currency, so treat a missing money field as “not known”, not as zero.

Where to read it

New integrations read money from three places, and all three carry the shape above:
  • *_money fields, beside the figure they replace: total_amount_money, price_money, max_amount_money, captured_total_money, and the rest in the migration table.
  • value inside objects that already carried an integer in minor units with its decimal_places, such as flight fares, select_ancillaries total_with_ancillaries and a booking’s confirmation.total_paid.
  • amount_money inside objects that hold money beside other members, such as a cancellation preview’s refund (which also carries basis) or a hotel tax line (which also carries description and included).
One rule covers all three:
value is an integer in minor units. Divide it by 10 ** decimal_places to get the amount, and show display when you need text.
value is not a display value. { "value": 15977, "decimal_places": 2 } is 159.77, not 15,977. Rendering value directly shows prices 100 times too high in a two-decimal currency. 15977 is a plausible long-haul fare, so a page of prices in the wrong unit can look like real data.

Convert it

Not every currency has 2 decimals

Hardcoding / 100 shows JPY and KRW prices 100 times too small and Kuwaiti dinar prices 10 times too high. Divide by the decimal_places sent with the figure.
Objects that carry value without being a *_money field can use a scale other than the ISO digits. Cached flight prices converted from another currency are one case: a JPY fare can arrive as { "value": 1561500, "currency": "JPY", "decimal_places": 2 }, which is JPY 15,615. The rule does not change: divide by the decimal_places on the object, never by digits you look up from the currency code. On *_money fields decimal_places is always the ISO digits.

Arithmetic: sum before you divide

To total several prices, such as the legs of a trip or the items in it, add the integer values and convert once at the end. Converting each figure first introduces floating-point error that shows up as totals one cent off.
Only add figures that share both currency and decimal_places. One response can hold more than one currency, for example a trip with a flight and a hotel priced by different providers. A trip whose items are priced in more than one currency has no totals.total_money on POST /v1/trip, for the same reason.

Fields that need more than the rule

Hotel cancellation steps

A step in a hotel cancellation_schedule (on hotel_search rates and on a quoted item’s hotel_terms) states the charge in one of three ways, and each has its own field: The deprecated amount on a step held any of the three, so it was a sum, a percentage or a count depending on type. Read the field that matches the step instead.

Paying with a Shared Payment Token

agent_spt_params.max_amount_money on the checkout response is the limit to scope the token to. Pass max_amount_money.value (minor units) and max_amount_money.currency to the token mint. The sandbox walkthrough shows the calls.

Committing a cancellation or refund

hotel_cancel_commit and flight_refund_commit take acknowledged, the refund the customer was shown on the preview. Copy the preview’s refund.amount_money into it unchanged:
The platform compares value, currency and decimal_places against the refund as it stands and ignores the other members. A figure that does not match is refused with 409 quote_drift and a fresh quote, and nothing is cancelled. Copy the object as it arrived; do not recompute or rescale it. The older form, the inline value, currency and decimal_places of refund itself, is still accepted. A flight refund preview that names no refund figure (a MANUAL_REQUIRED refund whose penalty is unknown) has nothing to acknowledge: commit it with manual_ok: true and without acknowledged.

What a booking was charged

booking.total_paid on get_booking is the gross amount captured for the booking: the original payment plus any later collections, such as the difference paid on an exchange. Refunds are not subtracted from it. It is absent in exactly two cases: nothing has been captured yet, or the booking was charged in more than one currency. If the captured amount cannot be read, get_booking returns an error rather than omitting the field, so an absent total_paid never means “unknown”.

Webhooks

Webhook payloads carry the same shape. booking.partial has data.items[].captured_amount_money and data.captured_total_money, and servicing.completed has data.refund and data.penalty. See Webhooks.

Using the CLI or SDK?

@gojinko/cli output (JSON is its default format) and @gojinko/api-client responses are the raw API body: neither converts money. The *_money fields appear in their output exactly as described on this page.

Prices look 100 times too high?

That symptom has one common cause: value was shown without dividing by 10 ** decimal_places. Check the raw JSON. If a fare you expect to be about $160 reads "value": 15977, "decimal_places": 2, show display or divide. Prices 100 times too small usually mean a hardcoded / 100 applied to a currency with decimal_places: 0, such as JPY.

Older fields

Before contract 0.26.0 the API returned money in several shapes, and some of them were in major units. Those fields are still sent, unchanged, beside their replacements. They are marked deprecated in the OpenAPI document, and no removal date is set yet. When one is set, it will be announced as described in Versioning & deprecation. New code reads the fields described above; this section is for code that still reads the older ones.

How to read the older shapes

The older fields follow a two-scale rule:
If the money object carries decimal_places, its number is an integer in minor units, whether it is named value or amount: divide by 10 ** decimal_places. If it has no decimal_places, amount is already in major units.
Apply the rule to the object in the response you received. The schemas mark decimal_places as optional on the shared Money shape, so generated types show it as optional even on endpoints that always send it.

Field-by-field migration

Each older field below stays in the response. So does a currency or *_display sibling that only described it. The replacement is a money value unless the row says otherwise. Trip, checkout and payment Hotels hotel_search nearby_alternatives[] carries the same rate fields as hotels[], with the same replacements. Post-booking Webhooks Not a money field: POST /v1/trip item kind Fields already in the money-value shape, such as flight fare total_price, get_booking servicing_summary[] and car search amounts, have no replacement and are not deprecated.