Xero Integration: Loan Repayments incorrectly booked as Realized Losses (P&L Debit) due to missing Liability Account mapping
L
Lagoon Coyote
## Summary
When syncing data to Xero, transactions labeled as "Loan Repayment" in Koinly are being posted as Debits to the "Realized P&L Account" (Account 265 in my setup). This incorrectly treats loan principal repayments as realized losses/expenses, causing massive discrepancies in the Profit & Loss report between Koinly and Xero.
## Impact
In my specific case, this bug resulted in
huge overstatement of losses
in Xero.- Koinly Tax Report:Shows correct Realized Gains/Losses.
- Xero P&L:Shows a massive loss because every loan repayment is treated as an expense.
## Current Behavior
For a transaction labeled
loan_repayment
(e.g., withdrawing USD/Stablecoins to pay off a Nexo loan), Koinly generates the following Journal Entry:*
Credit:
Crypto Fiat Asset Account [100] (Correct: Asset decreases)*
Debit:
Crypto Realized P&L Account [265] (INCORRECT
: This records the repayment as a P&L Loss)## Expected Behavior
A Loan Repayment is a Balance Sheet transaction, not a P&L transaction. It should reduce a Liability.
*
Credit:
Crypto Fiat Asset Account [100]*
Debit:
A designated Liability Account
(e.g., "Crypto Loans").## Root Cause / Missing Configuration
The current Xero Integration settings page (
https://app.koinly.io/p/settings/accounting
) does not
provide a field to map "Loan Repayments" or "Liabilities".It only allows mapping:
* Asset Accounts (Holdings, Fiat)
* P&L / Income / Expense Accounts
Because there is no "Liability Account" setting, the integration appears to default to the "Realized P&L Account" for the debit side of these withdrawals.
## My Configuration
My settings at
https://app.koinly.io/p/settings/accounting
are configured as follows:*
Crypto asset account:
[127] Crypto Asset Account - Holdings*
Fiat asset account (cash):
[100] Crypto Fiat Asset Account*
Realized P&L account:
[265] Crypto Realized P&L Account*
Fee account:
[405] Crypto Fee Account*
Income account:
[271] Crypto Income Account*
Expense account:
[430] Crypto Expense Account*
Gifts/donations/losses account:
[266] Crypto Gifts/Donations/Losses Account## Evidence / Example Transactions
Here are specific examples of Manual Journals created by Koinly that demonstrate the error:
Example 1:
Journal ID:
d4a7f100-3076-497a-aa60-16ef7710fc93
Date:
2025-11-05Narration:
Withdraw 49776.87 USD (net worth: 49776.87 USD, label: loan_repayment, desc: Crypto Repayment...)
Account Code | Account Name | Debit | Credit | Note
-------------|-------------------------------|------------|-----------|------------------------------
100 | Crypto Fiat Asset Account | | 43,293.43 | Asset decreases (Correct)
265 | Crypto Realized P&L Account | 43,293.43 | | Loss Recorded (Incorrect)
Example 2:
Journal ID:
81508b7d-39b6-4777-925b-cd4050f89860
Date:
2025-11-04Narration:
Withdraw 34665.57 USD (net worth: 34665.57 USD, label: loan_repayment, desc: Crypto Repayment...)
Account Code | Account Name | Debit | Credit | Note
-------------|-------------------------------|------------|-----------|------------------------------
100 | Crypto Fiat Asset Account | | 30,119.87 | Asset decreases (Correct)
265 | Crypto Realized P&L Account | 30,119.87 | | Loss Recorded (Incorrect)
Example 3:
Journal ID:
87951441-9a56-491f-954c-e5bc3fcc67d4
Date:
2025-11-11Narration:
Withdraw 33.51 USD (net worth: 33.51 USD, label: loan_repayment, desc: Crypto Repayment...)
Account Code | Account Name | Debit | Credit | Note
-------------|-------------------------------|------------|-----------|------------------------------
100 | Crypto Fiat Asset Account | | 28.99 | Asset decreases (Correct)
265 | Crypto Realized P&L Account | 28.99 | | Loss Recorded (Incorrect)
(Note: The amounts vary slightly from the narration due to cost basis calculations, but the accounting treatment is the issue).
## Suggested Fix
- Update the Xero Integration Settings:Add a new required field for "Liability Account" (or "Loan Account").
- Update the Sync Logic:Ensure that any transaction with the labelloan_repaymentdebits this new Liability Account instead of the Realized P&L Account.