# Currency and amount validation

> Validate transaction currency, amount precision, and payment method availability before creating a payment request.

Before you create a payment request, validate `orderCurrency`, `orderAmount`, and available payment methods on your server. `orderCurrency` is a three-letter ISO 4217 transaction currency. `orderAmount` is a positive decimal string in the transaction currency's display unit: send USD 99.99 as `99.99`, and send JPY 1000 as `1000` or `1000.00`.

<warning>

Do not generate `orderAmount` directly from JavaScript `number`, binary floating point values, or ad hoc rounded values. Calculate internally with integer values in the minor unit or a decimal library, confirm the amount, then format it as the string expected by the Onerway API.

</warning>

## Validation order

<steps level="3">

### Validate the currency code

`orderCurrency` must be an uppercase three-letter ISO 4217 alphabetic code, such as `USD`, `EUR`, or `JPY`. Do not pass currency symbols, country codes, unofficial abbreviations, or mixed-case values.

Do not use fund, precious metal, testing, or no-currency codes such as `XAU`, `XTS`, or `XXX` in payment requests unless Onerway has explicitly enabled them for your merchant, payment method, and transaction scenario.

### Validate amount format and precision

`orderAmount` must be a positive decimal string that uses `.` as the decimal separator. Do not include commas, spaces, currency symbols, plus or minus signs, or exponential notation.

| Minor unit | Validation rule | Common examples |
| --- | --- | --- |
| `0` | Must represent a whole amount; the decimal part may be omitted or contain zeros only | `JPY` accepts `1000` or `1000.00`; do not send `4.12` |
| `2` | Up to two decimals; integer amounts do not need `.00` | `USD` accepts `100`, `100.00`, or `99.99` |
| `3` | Up to three decimals; payment methods may still enforce additional limits | `KWD` accepts `10`, `10.500`, or `0.001` |

<note>

Currency precision should come from your enabled-currency configuration or ISO 4217 minor unit data. Do not hard-code all currencies as two-decimal currencies; zero-decimal currency and three-decimal currency values need separate handling.

</note>

### Validate payment method availability

Valid amount format does not guarantee that the transaction can be processed. Availability can also depend on the payment method, country or region, issuer, local payment provider, merchant configuration, and per-transaction limits.

Before you display a currency or let the customer enter an amount, call [List available payment methods](/payments/api-reference/endpoints/list-available-payment-methods) to filter methods by country or region, currency, amount, and merchant configuration. For each local payment method, never rely on currency alone.

### Validate the order total

If the request includes `txnOrderMsg.products`, discounts, shipping fees, or other order lines, calculate every line with the same currency and precision and make sure the line total matches `orderAmount`. Discount lines should use negative amounts when required by the endpoint field contract.

</steps>

## Request examples

```json
{
  "orderAmount": "99.99",
  "orderCurrency": "USD"
}
```

```json
{
  "orderAmount": "1000.00",
  "orderCurrency": "JPY"
}
```

```json
{
  "orderAmount": "10.500",
  "orderCurrency": "KWD"
}
```

## Server-side validation example

The example below only demonstrates amount format validation. In production, read enabled currencies, the minor unit, minimum amount, maximum amount, and available payment methods from your merchant configuration.

```ts
type CurrencyRule = {
  minorUnit: number
  minAmount?: string
  maxAmount?: string
}

const enabledCurrencies: Record<string, CurrencyRule> = {
  USD: { minorUnit: 2, minAmount: '0.01' },
  JPY: { minorUnit: 0, minAmount: '1' },
  KWD: { minorUnit: 3, minAmount: '0.001' }
}

function validateOrderAmount(amount: string, currency: string) {
  const code = currency.trim().toUpperCase()
  const rule = enabledCurrencies[code]

  if (!rule) {
    return { valid: false, reason: 'invalid_currency_code' }
  }

  if (!/^\d+(?:\.\d+)?$/.test(amount)) {
    return { valid: false, reason: 'invalid_amount_format' }
  }

  const [, fraction = ''] = amount.split('.')
  const hasTooManyDecimals = fraction.length > rule.minorUnit
  const isWholeAmountWithZeroFraction = rule.minorUnit === 0 && /^0*$/.test(fraction)
  if (hasTooManyDecimals && !isWholeAmountWithZeroFraction) {
    return { valid: false, reason: 'invalid_minor_unit' }
  }

  if (/^0+(?:\.0+)?$/.test(amount)) {
    return { valid: false, reason: 'amount_must_be_positive' }
  }

  return { valid: true, code, minorUnit: rule.minorUnit }
}
```

<tip>

Your frontend can limit decimal places and display formatting dynamically by currency. Treat the server-side result as authoritative, and do not silently truncate or round a customer-confirmed amount immediately before the API request.

</tip>

## Common rejection reasons

| Scenario | Cause | How to fix it |
| --- | --- | --- |
| `JPY` is sent as `4.12` | Zero-decimal currencies cannot contain non-zero decimals | Send a whole amount or an all-zero decimal form, such as `1000` or `1000.00`; otherwise the API may return `respCode=40000` with `Illegal parameter orderAmount` |
| `USD` is sent as `99.999` | More than two decimal places | Resolve precision before the customer confirms the amount |
| `KWD` is forced to two decimals | A generic amount component ignored three-decimal currency rules | Set precision dynamically in both the input component and server validation |
| `1,000.00` is submitted | API amounts do not accept thousands separators | Strip display formatting before submission and send only the decimal string |
| Payment method is unavailable | Currency format is valid, but method, region, or limits do not match | Query available payment methods first or confirm merchant configuration with Onerway |

## References

- [ISO 4217 currency codes](https://www.iso.org/iso-4217-currency-codes.html) — check alphabetic codes, numeric codes, and the minor unit
- [SIX Financial Data Standards](https://www.six-group.com/en/products-services/financial-information/market-reference-data/data-standards.html) — download ISO 4217 List One
- [List available payment methods](/payments/api-reference/endpoints/list-available-payment-methods) — filter available payment methods by transaction conditions
