# FX Payments and Realized Gain/Loss with the Accounting API

AP/AR platforms, treasury products, and embedded payments providers that move money across currencies need the destination ledger to reflect the realized FX impact at settlement time, not just the rate that was booked when the invoice or bill was issued. This guide shows how to use Apideck's [Accounting API](/apis/accounting/reference) to record foreign-currency invoices and bills, capture the settlement rate on the matching payment, and post realized gain or loss through a journal entry when the connector does not compute the variance automatically.

## Why a Unified API

Every accounting system implements multi-currency slightly differently: some require a home-currency setup flag, some auto-apply daily rates, some demand an explicit rate on every line. A unified API lets you ship one FX flow that works across all of them.

- No per-connector logic for where the rate field lives or what triggers it.
- One canonical place to set `currency` and `currency_rate` on documents and payments.
- One way to fetch the realized gain or loss GL account via [`GET /accounting/ledger-accounts`](/apis/accounting/reference#operation/ledgerAccountsAll).
- One fallback path through [`POST /accounting/journal-entries`](/apis/accounting/reference#operation/journalEntriesAdd) when manual variance booking is required.

## Resource mapping

The unified `currency` and `currency_rate` fields on invoices, bills, payments, and bill payments map to the following downstream concepts:

| Connector | Downstream object |
| --- | --- |
| QuickBooks | `ExchangeRate` on `Invoice` / `Bill` / `Payment`, posting to `Exchange Gain or Loss` |
| Xero | `CurrencyRate` on `Invoice` / `Bill` / `Payment`, posting to `Realised Currency Gains` |
| NetSuite | `exchangeRate` on `Transaction`, posting to per-subsidiary realized gain/loss accounts |
| Sage Intacct | `EXCH_RATE` on `AR Invoice` / `AP Bill`, posting to entity-level FX accounts |
| Exact Online | `RateFC` on `SalesInvoice` / `PurchaseInvoice`, sourced from the period exchange rate table |

## Walkthrough

This walkthrough models a USD-home company that issues a EUR invoice, then receives payment when the EUR/USD rate has moved. The result is a realized FX variance that lands in the configured gain/loss account.

### 1. Locate the realized FX account

Before posting any cross-currency activity, fetch the chart of accounts and identify the GL account where the connector posts realized FX. Use [`GET /accounting/ledger-accounts`](/apis/accounting/reference#operation/ledgerAccountsAll) and filter by classification.

```
GET https://unify.apideck.com/accounting/ledger-accounts?filter[classification]=expense
Authorization: Bearer <APIDECK_API_KEY>
x-apideck-app-id: app_01HRZ5E2Q9XK4D7JM2PT9N6V8B
x-apideck-consumer-id: usr_01HRZ5F8M3XJ7Q2K9N4PV6T1WC
x-apideck-service-id: xero
```

Cache the resulting `id` (for example `acct_01HRZ5G3K7P2N9V4M8T5JX1B6Q`) so later journal entries can reference it without a second lookup.

### 2. Issue the foreign-currency invoice

Send a EUR invoice with the rate that applies on the document date. The home-currency value is implicitly `total_amount * currency_rate`. Use [`POST /accounting/invoices`](/apis/accounting/reference#operation/invoicesAdd).

```json
{
  "invoice_number": "INV-2025-0417",
  "customer": {
    "id": "cust_01HRZ5H4N8P3Q5R7S9T1V2W4X6"
  },
  "invoice_date": "2025-04-17",
  "due_date": "2025-05-17",
  "currency": "EUR",
  "currency_rate": 1.0850,
  "line_items": [
    {
      "description": "Q2 platform subscription",
      "quantity": 1,
      "unit_price": 10000.00,
      "total_amount": 10000.00,
      "ledger_account": {
        "id": "acct_01HRZ5J5K2M4P6Q8R1T3V5W7Y9"
      }
    }
  ],
  "sub_total": 10000.00,
  "total": 10000.00,
  "status": "authorised"
}
```

At the booked rate of 1.0850, the AR receivable is recorded as 10,850 USD in the home ledger.

### 3. Record the payment at the settlement rate

When the customer settles, capture the settlement rate on the payment, not the booked rate. Allocate the payment to the original invoice and let the connector compute the variance against the AR balance. Send this to `POST /accounting/payments`. See [Payments add](/apis/accounting/reference#operation/paymentsAdd).

```json
{
  "transaction_date": "2025-05-15T09:30:00.000Z",
  "currency": "EUR",
  "currency_rate": 1.0795,
  "total_amount": 10000.00,
  "customer": {
    "id": "cust_01HRZ5H4N8P3Q5R7S9T1V2W4X6"
  },
  "accounts_receivable_account_id": "acct_01HRZ5K6L3N5P7Q9R2T4V6W8Y1",
  "payment_method": "wire_transfer",
  "reference": "WIRE-20250515-EUR",
  "allocations": [
    {
      "id": "inv_01HRZ5L7M4P6Q8R1T3V5W7Y9Z2",
      "type": "invoice",
      "amount": 10000.00
    }
  ],
  "type": "accounts_receivable",
  "status": "authorised"
}
```

The 10,000 EUR payment is worth 10,795 USD at the settlement rate. The AR account was carrying 10,850 USD against this invoice, so the connector recognizes a 55 USD realized loss and posts it to the configured FX account. The same shape applies on the AP side with [`POST /accounting/bill-payments`](/apis/accounting/reference#operation/billPaymentsAdd) referencing a foreign-currency bill from [`POST /accounting/bills`](/apis/accounting/reference#operation/billsAdd).

### 4. Book the variance manually when the connector does not

Some connectors will not auto-post a realized variance, especially when the payment currency differs from the document currency (a true cross-currency settlement). In that case, allocate the payment for the document-currency value and post the FX delta as a separate journal entry with [`POST /accounting/journal-entries`](/apis/accounting/reference#operation/journalEntriesAdd).

```json
{
  "title": "Realized FX on INV-2025-0417",
  "memo": "EUR receivable settled at 1.0795; booked at 1.0850",
  "posted_at": "2025-05-15T09:30:00.000Z",
  "currency": "USD",
  "currency_rate": 1.0,
  "line_items": [
    {
      "type": "debit",
      "total_amount": 55.00,
      "ledger_account": {
        "id": "acct_01HRZ5G3K7P2N9V4M8T5JX1B6Q",
        "name": "Realized FX Loss"
      },
      "description": "FX loss on INV-2025-0417 settlement"
    },
    {
      "type": "credit",
      "total_amount": 55.00,
      "ledger_account": {
        "id": "acct_01HRZ5K6L3N5P7Q9R2T4V6W8Y1",
        "name": "Accounts Receivable"
      },
      "description": "Clear residual AR balance from rate movement"
    }
  ]
}
```

The journal balances the AR clearing account and routes the variance to the realized FX account. Use the same pattern with the AP control account and a `Realized FX Gain` line for favourable swings.

### 5. Reconcile the result

After posting, validate the home-currency totals on the period reports. The balance sheet should now show zero residual on the AR control account for that invoice. Pull the period view through [`GET /accounting/balance-sheet`](/apis/accounting/reference#operation/balanceSheetOne) and the FX impact through [`GET /accounting/profit-and-loss`](/apis/accounting/reference#operation/profitAndLossOne) rather than reaggregating from raw invoices.

## Connector-specific behavior

The table below covers every connector currently in the catalog for this guide. Where a connector lacks write coverage on the resources used in the walkthrough, that is called out so you do not plan against an endpoint that is not callable. Always verify current support against the live coverage matrix.

| Connector | Notes |
| --- | --- |
| Access Financials | Invoices and payments writable. Bills, bill-payments, and journal entries are not in coverage, so realized FX must be modelled through payment-level allocations only. |
| Acumatica | Invoices, bills, payments, and journal entries writable; bill-payments are not in coverage, so AP-side variance has to flow through the payments resource or a manual journal. |
| Banqup | Invoices and customers are read-only. FX flows are not callable through Apideck on this connector today. |
| Campfire | Bills and journal entries writable; payments and bill-payments are limited. Use journal entries to record realized variance rather than relying on auto-posting. |
| Clearbooks UK | Invoices and bills are read-only. Cannot author FX documents or payments through Apideck. |
| Digits | Invoices, bills, payments, and bill-payments are not in coverage; journal entries are read-only. Not suitable for authoring FX flows. |
| DualEntry | Full read/write on invoices, bills, payments, bill-payments, and journal entries. Standard rate-on-document model. |
| Exact Online | Period exchange rates apply by default. Override per transaction with `currency_rate`. Invoices, bills, payments, bill-payments, and journal entries all writable. |
| Exact Online NL | Same period-rate behavior as Exact Online, with full read/write on the resources used here. |
| Exact Online UK | Bills are read-only on this regional variant. Invoices, payments, bill-payments, and journal entries writable; AP-side documents must originate elsewhere. |
| FreeAgent | Invoices and credit notes writable; bills are read-only and payments and bill-payments are not in coverage. Limited use for full FX settlement flows. |
| FreshBooks | Invoices, bills, payments, and bill-payments writable. Journal entries are read-only, so any manual variance must be reflected via payment allocations. |
| Intuit Enterprise Suite | Full read/write across all resources used here, including journal entries, attachments, and tracking categories for FX coding. |
| KashFlow | Invoices, payments, and journal entries are read-only and bills are not in coverage. Not suitable for authoring FX flows through Apideck. |
| Microsoft Dynamics 365 Business Central | Invoices, bills, bill-payments, and journal entries writable; the payments resource is read-only, so direct customer payments cannot be authored. AP-side FX settlement uses bill-payments. |
| Moneybird | Invoices, bills, and journal entries writable; payments and bill-payments are limited. Use journal entries to record realized FX. |
| MRI Software | Bills and journal entries writable; invoices and payments are not in coverage. Model FX impact directly through journal entries against the AP control account. |
| MYOB | Invoices and payments writable; bills, bill-payments, and journal entries are not in coverage. Only customer-side FX flows can be modelled. |
| MYOB Acumatica | Invoices, bills, payments, and journal entries writable; bill-payments are not in coverage. AP-side variance flows through the payments resource or a manual journal. |
| NetSuite | Foreign-currency transactions need the entity record's currency list to include the document currency. Realized gain/loss posts to per-subsidiary GL accounts under OneWorld; verify each subsidiary's account before posting variance journals. |
| Odoo | Full read/write on invoices, bills, payments, bill-payments, and journal entries. Standard mapping. |
| Pennylane | Invoices, bills, and journal entries writable; payments and bill-payments are not in coverage. Variance must be journaled manually. |
| Procountor FI | Invoices, bills, and journal entries writable; payments are read-only and bill-payments are not in coverage. Reconcile FX with journal entries posted to the realized gain/loss account. |
| QuickBooks | Multicurrency must be enabled in Company Settings before any non-base-currency transaction is accepted. Once enabled, the home currency cannot change. The `currency_rate` field is required on every non-base-currency entity. |
| Rillet | Invoices, bills, payments, and journal entries writable; bill-payments are limited. Standard rate-on-document model. |
| Sage Business Cloud Accounting | Invoices, bills, payments, and bill-payments writable; journal entries are read-only. Realized FX must come through the connector's automatic posting on the payment. |
| Sage Intacct | Multi-currency is a paid module. Each entity has its own base currency, and payments across entities require explicit FX rate entries. Configure the realized gain/loss account at the entity level. |
| Sage Intacct REST | Not in coverage for the resources used in this guide. |
| Stripe | Invoices writable; payments are read-only because Stripe handles settlement and FX natively on its own ledger. Use Stripe's payouts as the source of truth and post a journal entry into the destination accounting connector for the realized FX impact. |
| Visma Netvisor | Invoices, bills, and payments writable; journal entries are read-only and bill-payments are not in coverage. Rely on payment-level allocation to surface realized variance. |
| Wave | Invoices writable; bills, payments, and bill-payments are not in coverage. Limited FX support through Apideck. |
| Workday | Invoices, bills, payments, and journal entries writable; bill-payments are read-only, so AP settlement variance has to be journaled. |
| Xero | Multicurrency requires the Established plan or higher. Daily rates auto-apply when `currency_rate` is omitted; an explicit value overrides them. Settlement variance posts to the `Realised Currency Gains` account configured per organisation. |
| Yuki | Journal entries writable; invoices are read-only and payments are not in coverage. Use journal entries to record realized FX. |
| Zoho Books | Full read/write on invoices, bills, payments, bill-payments, and journal entries. Standard rate-on-document model with realized gain/loss posting to a configured GL account. |

### QuickBooks

Multicurrency is a one-way switch. Toggle it on through Company Settings before issuing any foreign-currency invoice or bill, because the home currency becomes immutable afterwards. With the flag enabled, omit `currency_rate` to fall back to QuickBooks' daily rate or set it explicitly to lock the booked rate. Realized FX automatically posts to the `Exchange Gain or Loss` account on payment.

### Xero

Xero auto-applies a daily rate when `currency_rate` is not provided. Send an explicit value to lock the rate at the moment of booking, especially when reconciling against an external treasury system that captured its own rate. The realized variance posts to the `Realised Currency Gains` account selected under organisation settings; if that account has not been configured, the payment will reject.

### NetSuite

Confirm that the customer or vendor entity record has the document currency enabled before posting any foreign-currency transaction. Under OneWorld, each subsidiary owns its own realized gain/loss accounts, so a payment that touches multiple subsidiaries needs the rate set explicitly and the destination accounts validated per subsidiary. Multibook accounting introduces additional rate types (book-specific) that must align with the primary book's `exchangeRate`.

### Sage Intacct

Multi-currency is gated behind a paid module. Once enabled, each top-level entity carries its own base currency, and inter-entity payments require an explicit FX rate at posting time. Verify the realized gain and loss accounts on each entity definition before going live.

### Exact Online

Exact Online maintains a period exchange rate table and applies the period rate by default. Setting `currency_rate` on a transaction overrides the period rate for that document only and does not back-fill the rate table. For systematic settlement-time variance booking, journal the difference rather than overwriting the period rate.

## Next steps

- [Mark Invoices and Bills as Paid](/guides/mark-invoices-as-paid) for the underlying allocation pattern used in step 3.
- [Handling Bills and Expenses](/guides/expenses-bills) for foreign-currency AP scenarios.
- [Accounting API reference](/apis/accounting/reference) for full payload schemas on payments, bill payments, and journal entries.
