Your rounding discrepancies stem from a combination of decimal precision handling, exchange rate calculation sequence, and currency-specific rounding rules. Here’s how to achieve consistent results between API and manual postings:
1. Decimal Precision Configuration
Verify your currency configuration in transaction OB08:
Currency: JPY
Decimals: 0 (zero decimal places)
Rounding: Commercial (0.5 rounds up)
For EUR:
Currency: EUR
Decimals: 2
Rounding: Commercial
In transaction OB22 (Exchange Rate Type configuration), verify:
- Exchange Rate Type: M (standard)
- Decimal Places: 5 (for rate precision)
- Inverted Rate: Not selected for EUR/JPY
The API uses these settings, but the calculation sequence matters more than the configuration.
2. Exchange Rate Rounding Logic
The key difference is WHEN rounding occurs in the calculation chain:
FB60 Manual Posting (Line-by-Line):
Line 1: EUR 1,234.56 × 163.45000 = JPY 201,788.732 → rounds to JPY 201,789
Line 2: EUR 567.89 × 163.45000 = JPY 92,821.6405 → rounds to JPY 92,822
Line 3: EUR 890.12 × 163.45000 = JPY 145,488.114 → rounds to JPY 145,488
Total: JPY 440,099
API Posting (Potential Total-First):
Total EUR: 1,234.56 + 567.89 + 890.12 = EUR 2,692.57
Convert: EUR 2,692.57 × 163.45000 = JPY 440,098.4865 → rounds to JPY 440,098
Difference: 1 JPY due to rounding sequence
To force line-level rounding in the API, include line items explicitly:
POST /API_BILLING_DOCUMENT_SRV/A_BillingDocument
{
"BillingDocumentType": "F2",
"SoldToParty": "IC-2000",
"DocumentCurrency": "EUR",
"DocumentDate": "2025-07-11",
"ExchangeRateDate": "2025-07-11",
"ExchangeRateType": "M",
"ExchangeRate": "163.45000",
"to_Item": [
{
"BillingDocumentItem": "10",
"NetAmount": "1234.56",
"TransactionCurrency": "EUR",
"AccountingExchangeRate": "163.45000"
},
{
"BillingDocumentItem": "20",
"NetAmount": "567.89",
"TransactionCurrency": "EUR",
"AccountingExchangeRate": "163.45000"
}
]
}
By specifying AccountingExchangeRate at the line item level, you force the API to:
- Convert each line individually
- Round each result to JPY (0 decimals)
- Sum the rounded line totals
This matches FB60’s calculation sequence exactly.
3. Currency Conversion Logic Alignment
Ensure these fields are populated in your API request:
- ExchangeRateType: Must match FB60 (typically “M” for standard rates)
- ExchangeRateDate: Date for rate lookup (usually document date)
- ExchangeRate: Explicit rate value with 5 decimal precision (163.45000)
- DocumentCurrency: Source currency (EUR)
- CompanyCodeCurrency: Target currency (JPY) - if different from document currency
The API’s currency conversion follows this logic:
// Pseudocode for API conversion:
1. Lookup exchange rate from TCURR table using ExchangeRateType and ExchangeRateDate
2. For each line item:
a. Amount_EUR × ExchangeRate = Amount_JPY_unrounded
b. Apply currency-specific rounding (0 decimals for JPY)
c. Store rounded Amount_JPY for line
3. Sum all line-level Amount_JPY values for document total
4. Validate sum matches header TotalNetAmount (if provided)
To ensure the API uses the same rate as FB60:
- Query the rate first: `GET /API_EXCHANGERATE_SRV/A_ExchangeRate?$filter=SourceCurrency eq ‘EUR’ and TargetCurrency eq ‘JPY’ and ExchangeRateDate eq datetime’2025-07-11’
- Use the returned rate explicitly in your billing document post
- Include all 5 decimal places (163.45000, not 163.45)
4. Reconciliation Validation
Implement automated reconciliation to catch any remaining discrepancies:
// Pseudocode for validation:
1. After API posting, retrieve the created billing document
GET /A_BillingDocument('{DocumentNumber}')?$expand=to_Item
2. For each line item, validate:
a. EUR_amount × Exchange_rate = Expected_JPY_amount (rounded)
b. Compare Expected_JPY_amount to Actual_JPY_amount from API
c. Flag if difference > 0 JPY
3. Validate document total:
a. Sum all line-level JPY amounts
b. Compare to document header TotalNetAmount in JPY
c. Acceptable variance: 0 JPY (must be exact)
4. If discrepancy found:
a. Log the document number and difference
b. Trigger manual review workflow
c. Optionally reverse and repost with corrected values
Implement this validation immediately after each API post to catch issues in real-time.
Additional Configuration Checks:
- Transaction OB09: Verify intercompany-specific rounding rules don’t override standard behavior
- Transaction OBBS: Check posting period variant allows the document date
- Transaction OBY6: Confirm company code currency is JPY for the receiving entity
- Table TCURR: Verify exchange rate entry has correct ratio fields (UKURS=1, FFACT=1, TFACT=1 for direct EUR/JPY rates)
Common Pitfalls to Avoid:
- Using TotalNetAmount in header without line items: This forces total-first conversion
- Omitting ExchangeRate field: API uses system default which may differ from FB60’s lookup
- Wrong decimal precision: Using 163.45 instead of 163.45000 can cause calculation differences
- Mixing currency in line items: All lines must use same TransactionCurrency as header
- Not specifying ExchangeRateType: Different rate types (M, B, G) yield different rates
Testing Approach:
Create a test case with known values:
Line 1: EUR 100.00 × 163.45000 = JPY 16,345
Line 2: EUR 0.01 × 163.45000 = JPY 1.6345 → rounds to JPY 2
Line 3: EUR 0.01 × 163.45000 = JPY 1.6345 → rounds to JPY 2
Total: JPY 16,349
Post this via API with explicit line items and rates. Compare the resulting JPY amounts to manual FB60 posting of the same data. They should match exactly.
By implementing line-level exchange rate specification, using 5-decimal precision rates, forcing line-by-line conversion sequence, and validating results immediately after posting, you’ll eliminate the rounding discrepancies. The key is matching the API’s calculation flow to FB60’s line-level-then-sum approach rather than sum-then-convert.