ZenrateBlog

2026-05-27 · Koryu, Endots LLC

exportfreeeMoneyForwardQuickBooksXero

Exporting Japanese expense reports: the freee, MoneyForward, QuickBooks, and Xero gotchas

I spent an hour one evening debugging why a 47-row expense CSV would not import into freee. The file looked correct in a text editor. The columns were named exactly what I thought freee expected. Comma-separated, UTF-8 encoded, dates in YYYY/MM/DD as freee's import documentation suggested. Import attempted: zero rows imported, one cryptic error per row.

The problem turned out to be one column: 勘定科目コード (account category code). I had used my company's old account codes from the previous accounting software. freee's import was rejecting every row because none of those codes existed in this freee account. The import was working exactly as designed — the rows weren't malformed, they were referencing accounts that didn't exist. Once I re-mapped to freee's actual codes, the import succeeded immediately.

This is the kind of gotcha that "export to CSV and you're done" features create. The CSV is technically correct; the import fails for reasons that have nothing to do with the file format and everything to do with platform-specific data conventions. An export feature that produces a CSV the target system will not import is worse than no export feature — it wastes the user's time first, before they realize they need to do the import work manually.

Zenrate exports to four platforms: freee, MoneyForward Cloud, QuickBooks Online, and Xero. Each has its own set of gotchas. Here's what I learned the hard way and how Zenrate's exports handle each.

freee gotchas

freee's import format is documented but the documentation tends to lag the actual import endpoint. The most common failure modes I see:

Required columns and their exact Japanese names. freee's import expects specific column headers in Japanese: 発生日 (transaction date), 借方勘定科目 (debit account), 借方金額 (debit amount), 貸方勘定科目 (credit account), 貸方金額 (credit amount), 摘要 (memo). Variations like 取引日 instead of 発生日 are silently ignored, which means a CSV that looks "obviously correct" to a human reader can produce zero imported rows because the columns weren't recognized as required fields. Zenrate's freee export uses the exact strings freee currently expects; this is tracked against freee's published format and tested quarterly.

Date format ambiguity. freee accepts both YYYY/MM/DD and YYYY-MM-DD in the date column. Most of the time. The exception is when a single CSV mixes formats — some rows YYYY/MM/DD and others YYYY-MM-DD — in which case the parser sometimes interprets the second batch as US-format MM/DD/YYYY and silently shifts everything by months. Zenrate normalizes all dates to a single format per export to avoid this.

Tax category mapping. Each expense line needs a tax category (税区分 / 税率) that maps to one of freee's predefined tax categories. The mapping is account-dependent — what's "10% reduced rate" in one account's setup may have a different internal code in another. Zenrate's export uses freee's default tax category codes; if your account has customized them, the import will reject rows that reference codes you've renamed. The fix is to either restore default codes on the freee side or to customize Zenrate's export mapping for your specific account, which we don't expose in the UI today but can be done by editing the export configuration.

The 勘定科目 (account code) existence requirement. This is the one that bit me. Every row's account code must exist as an account in your freee account. freee won't auto-create accounts on import; it'll reject the row. The first export from Zenrate to a new freee account always requires a one-time setup pass where you confirm the account codes match.

Multi-currency in freee. freee added multi-currency support relatively recently. Older freee accounts may not have it enabled; the import will reject foreign-currency lines if multi-currency isn't turned on. The check is in account settings → 通貨設定. Zenrate exports include both the foreign-currency amount (in the original currency column) and the JPY-translated amount; if multi-currency is off, you can still import the JPY amounts but the foreign-currency columns get ignored.

MoneyForward Cloud gotchas

MoneyForward's import works differently enough from freee's that the same data can't just be re-shaped — the column set is genuinely different.

Encoding. This is the one I see catch people most often. MoneyForward Cloud's import historically expected Shift-JIS encoding for CSV files, which is a problem because most modern tools (especially anything running on macOS or Linux) produce UTF-8 by default. A UTF-8 file imported into MoneyForward's older import paths produces garbled Japanese characters in the memo and account-name columns, which then fail validation against MoneyForward's expected character set. The newer import paths accept UTF-8, but the legacy ones don't, and which path a user lands on depends on their MoneyForward account settings.

Zenrate's MoneyForward export defaults to UTF-8 for new imports and offers a Shift-JIS toggle for users hitting the legacy path. The toggle is exposed in the export dialog rather than buried in settings, because the wrong choice fails silently with corrupted character display rather than an obvious error.

Column set. MoneyForward's required columns are different from freee's. The most surprising difference is that MoneyForward uses a single 金額 (amount) column where freee uses separate 借方金額 / 貸方金額 (debit / credit) columns; MoneyForward derives debit/credit from the account type rather than from explicit columns. A Zenrate user switching from freee to MoneyForward sometimes assumes the column structure transfers, and it doesn't.

Amount precision. Yen amounts are typically integer in both freee and MoneyForward; foreign-currency amounts are 2 decimal places. MoneyForward will accept more decimal places but will round on import in a way that doesn't always match Zenrate's stored value, leading to small reconciliation gaps. Zenrate's MoneyForward export rounds explicitly to MoneyForward's expected precision on the way out, so what you see in MoneyForward matches what was exported.

Department tagging. MoneyForward supports department codes (部門コード) on each line. Zenrate doesn't currently capture department metadata per receipt; the export leaves this column blank and MoneyForward handles blank departments fine, but if your accounting workflow relies on department-tagged imports you'll need to add the codes manually post-import or extend Zenrate's data model to capture them.

QuickBooks Online gotchas

QuickBooks has multiple import paths — IIF (legacy desktop format), CSV via Banking → File Upload, and the QuickBooks Online API — each with different rules. Zenrate's QuickBooks export targets the CSV-via-File-Upload path because it's the most accessible to small businesses without API integration.

IIF is legacy. Don't use IIF unless you're explicitly importing into QuickBooks Desktop, which is a separate product from QuickBooks Online. IIF imports into QuickBooks Online are deprecated; the official path is CSV.

Multi-currency must be enabled before import. QuickBooks Online treats multi-currency as a one-way toggle: once you enable it for an account, you can never disable it. Many small US QuickBooks Online accounts have multi-currency off by default and don't enable it because of the irreversibility. Zenrate's QuickBooks export for foreign-currency transactions assumes multi-currency is on; if it isn't, the import will reject foreign-currency lines. The error message from QuickBooks is helpful enough that users figure this out, but it's worth knowing in advance.

Category mapping is account-specific. QuickBooks's "categories" are essentially the same concept as freee's accounts — they need to exist in the target account before import. The default category names (Office Supplies, Travel, Meals & Entertainment) are common but not universal; some businesses have customized them. Zenrate's QuickBooks export uses the default category names; if your account uses custom names, the import will create new entries with the default names alongside your custom ones, which is rarely what you want. The fix is to either revert to default names temporarily for import, or to manually re-map after.

Date format is locale-specific. QuickBooks Online uses the date format associated with the account's region setting. A US account expects MM/DD/YYYY; a UK account expects DD/MM/YYYY. Zenrate's export sets the date format based on the user's selected QuickBooks region in the export dialog. Getting this wrong produces silent date-shift errors that are hard to spot until reconciliation.

Xero gotchas

Xero is the most forgiving of the four on CSV format but the strictest on a few specific data conventions.

Date parsing across locales. Xero infers date format from the column position in the file plus the account's locale setting. If you import a CSV with dates in one locale into an account set to another locale, Xero will silently swap day and month for dates where the swap produces a valid date and reject dates where it doesn't. So a file with 03/05/2024 imported into a Xero AU account (expecting DD/MM/YYYY) will read it as May 3; the same file imported into a Xero US account (expecting MM/DD/YYYY) will read it as March 5. Both succeed; the resulting dates are different. Zenrate's Xero export uses ISO format (YYYY-MM-DD), which Xero accepts unambiguously regardless of locale.

Tracking categories. Xero's "tracking categories" are essentially department/region/project tags applied to lines. They must be set up in Xero before import; the import will reject lines that reference tracking categories that don't exist. Zenrate's export doesn't populate tracking categories today (we don't capture the data) but doesn't reference any either, so this only matters if you're hand-editing exports to add tags.

Bank feed reconciliation conflicts. Xero has automatic bank feed reconciliation. If you import expense entries that overlap dates with transactions already pulled from a bank feed, you can end up with duplicate entries — one from the feed, one from the import — that need manual reconciliation. The recommended workflow is to import Zenrate's expense export and then run Xero's "match" step against the bank feed; mismatches surface as items needing manual matching. This is a workflow issue, not a Zenrate-vs-Xero data issue, but it's the most common source of post-import confusion.

Multi-currency in Xero. Xero handles multi-currency cleanly when it's enabled, but enabling it requires a higher-tier plan than the basic Standard plan. Foreign-currency imports into a Standard-plan account will be rejected. The error message is clear; users on Standard either upgrade or import only home-currency entries.

How Zenrate handles each, in summary

The per-platform exports use the exact column headers and data formats each tool expects. The encoding is selectable for MoneyForward (UTF-8 default; Shift-JIS available for legacy import paths). Date format is set per export target, not per user — the Xero export always uses ISO; the QuickBooks export uses MM/DD/YYYY for US accounts and DD/MM/YYYY for UK/AU accounts based on the region selector in the export dialog.

The currency, amount format, and category-code conventions are also per-target. The export code lives in `packages/core/src/export/` with one file per platform — `freee.ts`, `moneyforward.ts`, `quickbooks.ts`, `xero.ts` — plus a registry that maps the user's selected target to the right export function. When a platform changes its import format (which all four have done in the past), the change is contained to one file rather than scattered across the codebase.

I re-test each export against the target platform's current import endpoint quarterly. This is manual work and it's not glamorous, but it's the only way to catch schema changes before users do.

The underlying principle

The export feature that "exports to spreadsheet and lets the user figure out the rest" is the lazy version of the problem. It's also the version that wastes the user's time the most. An hour debugging why freee won't accept a CSV is an hour the user didn't budget for, and the user blames Zenrate even though the underlying problem is freee's strict validation. The right design is to do the platform-specific mapping inside the export, so the file Zenrate produces actually imports without further work.

This is harder than it looks because each platform's expectations change over time. The quarterly re-test is the cost of keeping this commitment. Skipping it would let exports drift out of sync with platform changes, which is exactly the failure mode "export to spreadsheet" features have.

Why this matters for Zenrate

The export targets in `packages/core/src/export/` are the surface where Zenrate's data leaves the system and becomes someone else's responsibility. Getting them right is the difference between "Zenrate handles my expense workflow" and "Zenrate helps me capture receipts but I still have to redo the import." The platform-specific exports — with their handling of column names, encodings, date formats, tax categories, and account codes — exist because the alternative is wasting an hour of every user's time on every import.

— Koryu, Endots LLC

Try Zenrate

Convert currencies with real-time rates and generate expense reports.

Open Converter