- 01It started with unrecorded transactions piling up
- 02How the system works
- 03Fetching unprocessed transactions
- 04Tricks for searching email
- 05Categorization rules
- 06Registering it as an expense
- 07Regularly hunting down expenses filed in the wrong category
- 08Leave the final call to a professional
- 09What I’ve noticed after trying it
- 10Who this suits
- 11Summary
Good morning. It’s まさきん.
I run a small side business on my own. My accounting SaaS handles the bookkeeping itself, but trying to remember what each card charge was actually for turned out to be a surprisingly tedious chore.
So I built a system where AI cross-checks my card transactions against email receipts and automates the expense categorization too. In this post, I’ll cover how I call the APIs and the pitfalls I actually ran into.
It started with unrecorded transactions piling up
When you link a card to your accounting SaaS, the transactions get imported automatically. But the software has no idea what each payment was for. So you end up recording entries later, relying on memory.
And memory fades fast. That’s why I decided to hand the remembering part over to AI.
How the system works
Here’s what it does, in four steps:
- Fetch card transactions that haven’t been recorded yet from the accounting SaaS API
- Search for order confirmation and receipt emails with the same amount and a nearby date
- Match the two to identify what the purchase was
- Based on what was identified, categorize the expense and register it as a transaction in the accounting SaaS
The key point is that neither the transaction data alone nor the emails alone are enough. You can only pin down what a purchase was by matching the two.
Fetching unprocessed transactions
When you fetch transactions through the accounting SaaS API, each one comes with a flag showing its processing status. To target only the unregistered ones, you filter on this flag.
GET /api/1/wallet_txns
query: { company_id, start_date, end_date, limit: 100 }
Of the transactions returned, only those with an “unregistered” status and an unreconciled amount greater than 0 get processed. Anything already registered or marked as ignored is excluded. Results are often paginated, so I check across multiple date ranges to make sure nothing slips through when a period crosses into a new month.
Tricks for searching email
If you feed full email bodies straight to the AI, there’s so much text that you can hit the token limit. So I narrow things down first before passing any content along.
First, I run a date-range search on the sender addresses used for order confirmations and receipts.
search_threads query: "from:[email protected] after:2026/09/01 before:2026/09/30"
Even once I find matching emails, passing the entire body to the AI can still hit the token limit. In that case, I run a keyword search against files where the email bodies are saved and pull out only the lines containing the amount or product name.
# Example: narrowing saved email files down to those with a matching amount and nearby date
grep -l "3,980円" ./mail_archive/*.eml | xargs grep -l "2026-09"
Filtering on two clues, amount and date, cuts the candidates down to just a handful. Only after narrowing things that far do I pass just the relevant parts to the AI for matching. Many emails can be handled with just the subject line and the opening snippet, so the trick is to fetch only what you actually need.
Spending that gets classified as expenses also includes fixed costs like phone and internet bills. A smartphone you also use for work is a classic example of something that’s hard to split between business and personal use. With that in mind, reviewing your plan might be worth considering.
Clicking this opens the Rakuten login page. Once you log in, you’ll see the campaign details.
Categorization rules
Once a purchase is identified, I sort it into one of three categories.
| Category | Description | Treatment |
|---|---|---|
| Direct side business expenses | Supplies and services directly related to the side business | Recorded as an expense with a note on the business-use ratio |
| Reference books and materials | Books and the like for understanding the work | Recorded as a general materials expense |
| Personal spending | Private purchases unrelated to the side business | Excluded from expenses (handled as an owner’s drawing) |
For anything ambiguous, I avoid forcing it into the expense column. If I’m not confident about a purchase, I treat it as personal spending for now and flag it for review later.
Registering it as an expense
Once the category is decided, I register it as a transaction through the accounting SaaS API.
POST /api/1/deals
body: {
company_id,
issue_date: "2026-09-15",
type: "expense",
details: [{
account_item_id: <expense account ID>,
amount: <amount>,
description: "◯◯ supplies (note on business-use ratio)"
}],
payments: [{
amount: <amount>, date: "2026-09-15",
from_walletable_type: "credit_card", from_walletable_id: <card ID>
}]
}
There’s one thing to watch out for here. This registration creates a new transaction inside the accounting SaaS. It does not automatically link to (reconcile) the original unprocessed card transaction. Registering the transaction alone leaves the card transaction’s status as unprocessed.
So after registering, I always go into the accounting SaaS interface and manually link the card transaction to the newly created one. Skip this step and the same expense gets counted twice, so I’m careful about it.
Regularly hunting down expenses filed in the wrong category
Even with automation, categorization mistakes never drop to zero. So once a month, I have the AI dig up records that look related to the side business but have been left sitting in a general category.
Specifically, I pull the profit and loss report via the API and identify expenses recorded under general accounts rather than the accounts dedicated to the side business. Then I fetch the breakdown for each account through the transaction list API, and have the AI compile a list of records that, based on keywords in the description field and spending patterns, probably should have been moved into the side business category.
When I find a matching transaction, I swap the account using PUT.
PUT /api/1/deals/{transaction ID}
body: { company_id, issue_date, type: "expense",
details: [{ id: <existing detail ID>, account_item_id: <correct account ID>, amount, description }] }
There’s a catch here too. If you send details without including the existing detail ID, it’s treated as a new addition rather than an update. Carrying over the existing ID is essential for the reclassification to work correctly.
I review everything that gets flagged myself and only reassign the ones that actually need it.
Leave the final call to a professional
I want to stress this point. This system only streamlines the groundwork for bookkeeping. For final decisions on how expenses are classified and whether the business-use ratios are reasonable, I follow the judgment of a professional such as a tax accountant.
The AI’s categorization is only a first draft. Especially for anything involving business-use ratios, I don’t move forward on my own judgment alone. I run things on the assumption that I’ll check with a professional.
What I’ve noticed after trying it
The biggest relief is no longer having to remember what each payment was for. As long as there’s an email record, I can leave identifying the purchase to the AI.
That said, I always do the final check on categorization with my own eyes. The line between personal spending and business expenses in particular feels risky to leave to purely mechanical judgment.
Who this suits
- People with a side business or sole proprietorship who pay for lots of expenses by card and tend to put off bookkeeping
- People who make many purchases that leave order confirmations or receipts in their email
- People who are fairly comfortable with accounting SaaS API integrations and using AI
Summary
The idea of matching card transactions against emails isn’t anything special. But whether you do it by hand every time or hand it off to a system makes a huge difference in how much effort it takes.
If you keep in mind the pitfall that registering via the API doesn’t reconcile the card transaction, I think you’ll be less likely to stumble when you actually build this yourself. Without abandoning the principle of leaving the final call to a professional, I feel I’ve managed to systematize just the groundwork part nicely.
While sorting all this out, my phone and internet costs also came up for review. My smartphone bill, which I also use for work, was the expense where splitting business and personal use was hardest to judge. In that case, it might make sense to sort out the plan itself first.
Clicking this opens the Rakuten login page. Once you log in, you’ll see the campaign details.
This article contains affiliate advertising. If you sign up for a product or service through a link on this site, we may receive compensation from the partner company. The site operator is also an employee of Rakuten Group and may receive compensation through an employee referral program. The content and opinions here are based on the operator’s own experience and research regardless of any advertising relationship, but please read with the above in mind. See the Disclaimer & Affiliate Disclosure for details. Disclaimer & Affiliate Disclosure
This article includes machine-translated content. Please check the official Rakuten Mobile multilingual page for exact terms.
If you have concerns about Rakuten Mobile coverage or signal quality, you can consult through the official signal improvement request form .