Amounts and data formats
This page primarily covers /openapi/v1 products and orders. Account top-ups, payment gateways and administrative APIs have different fields and status contracts.
Amounts use a fixed eight-decimal scale
Current product and order API amount fields use a 10^-8 scale:
display amount = API integer / 100000000This differs from a currencyβs display precision. currency_decimals and payment_currency_decimals describe currency precision; they do not change the integer scale.
| Amount | API integer |
|---|---|
| 1 TDC | 100000000 |
| 1.25 USD | 125000000 |
| 0.01 USD | 1000000 |
Do not divide 125000000 by 100 merely because USD normally displays two decimal places.
General collection uses currency minor units
/openapi/v1/merchant-payments uses amount_minor at currency precision: submit 1050 for USD 10.50 (2 decimals) or 1050000000 for TDC 10.50 (8 decimals). Do not reuse catalog ordersβ uniform eight-decimal scale. Its status is a string, expires_at and occurred_at are RFC 3339 timestamps, and filtered lists return items and require an external reference or order number. See General merchant collection.
Product versus payment amounts
| Fields | Meaning |
|---|---|
currency, currency_decimals | Product currency and display precision |
total_amount, discount_amount | Product total and discount |
payment_currency, payment_currency_decimals | Payment currency and precision |
payment_subtotal, payment_handling_amount, payment_pay_amount | Subtotal, fee and final charge in payment currency |
Use payment currency with its corresponding amounts in payment confirmation. Do not attach the wrong currency label, add amounts across currencies or reprice historical orders using live rates.
Rates and amounts have different scales
Fixed fees and monetary caps use the eight-decimal amount scale. Integer rates such as handling_fee_percent use ppm: 10000 means 1% and 40000 means 4%. Exchange-rate multipliers such as tdc_per_unit are decimal strings, not nano integers.
A channel percentage fee applies to the amount plus the fixed fee; the cap limits only the percentage portion. For a 10 USD top-up with a 4 USD fixed fee and 4% rate, the percentage portion is 0.56 USD and the total fee is 4.56 USD. A UI input of 4% becomes 40000 in the API. Prefer the server quote over a separately calculated total.
JavaScript precision
Amounts are JSON integers. Beyond JavaScriptβs safe integer range, ordinary JSON.parse can already lose precision. Converting that rounded value to BigInt cannot recover it.
Use JSON parsing that preserves large integers and perform money arithmetic with integers or a decimal fixed-point library. Use ordinary Number only for values confirmed to be within its safe range. See MDN on safe integersΒ .
Keep the two status contracts separate
Order detail status | Meaning |
|---|---|
| 0 | Awaiting payment |
| 1 | Processing, payment confirmed |
| 2 | Cancelled |
| 3 | Completed |
The status from GET /openapi/v1/orders/{order_no}/payment instead means:
Payment query status | Meaning |
|---|---|
| 0 | Awaiting payment |
| 1 | Paid, including processing and completed orders |
| 2 | Cancelled |
When the payment query returns 1, read order details to determine whether fulfillment is complete.
Account top-up gateway queries use a separate status contract: 1000 (UnPaid), 1001 (Paid), 1002 (Complete) and 1003 (Expired), alongside status_label. Top-up history uses another field, pay_status. Do not map these to the OpenAPI 0/1/2 values above. These account endpoints require a platform session and are not third-party OAuth OpenAPI routes.
Success and error responses
Successful OpenAPI responses return the resource or list directly, without a common data wrapper. OAuth errors use a string error and error_description. Transaction validation or business errors may instead contain a numeric code, textual error and optional error_description. Check the HTTP status and actual response shape rather than assuming one business error schema for every endpoint.
Identifiers, pagination and time
- Keep product, order and client identifiers as strings.
- Product lists return
list,total,pageandlimit. Defaults are page 1 and limit 20. Valid limits are 1β100; out-of-range limits currently fall back to 20. - Payment creation returns
expire_timeas a Unix timestamp in seconds. OAuthexpires_inis a lifetime in seconds from issuance. They are not interchangeable. - Order dates are
YYYY-MM-DD HH:mm:ssstrings ornull, without a time zone. Do not render empty dates as 1970 or assume UTC. Theexpire_timein top-up history is also a date string, unlike the Unix seconds field with the same name in payment creation.