Skip to main content
Period-end accruals usually start as a raw export nobody wants to pivot by hand: a timesheet dump, an open purchase order report, a contractor invoice queue. This guide brings that export into Claude, works the numbers, and posts the result to DualEntry as a balanced journal entry with its reversal already scheduled. The whole sequence runs in one Claude conversation. You do not export anything back out, and you do not retype figures into the ledger. To do the same job inside DualEntry instead, see how to draft accruals with Copilot and a scheduled agent. The difference is where the entry is created and how it is confirmed: Copilot proposes an entry in a preview and nothing reaches the general ledger until you post it yourself, while the MCP server’s save_record writes to the ledger as soon as Claude calls it. Prefer the Copilot path when you want a preview between the proposal and the posting.

Before you start

Connect Claude to DualEntry first, because none of the steps below work without the tools attached. Follow Quickstart: DualEntry MCP Server and confirm Claude lists the DualEntry tools before you continue. You also need:
  • A DualEntry role with create permission for journal entries: MCP access mirrors your dashboard role, so if you cannot post a journal entry in DualEntry, Claude cannot post one for you.
  • Access to the company you intend to post to: Company-level restrictions apply to the tools the same way they apply to the dashboard.
  • An open accounting period for the posting date: A locked period rejects the entry.
  • The accrual accounts already in your chart of accounts: Create them in DualEntry first if they do not exist.
This guide assumes you know what the accrual should be. Claude does the arithmetic and the grouping, not the accounting judgment.
The save_record tool posts a real record immediately. There is no draft stage, no preview, and no confirmation prompt between Claude deciding to call it and the entry hitting your ledger. Review the numbers in the conversation before you tell Claude to post, and treat “post it” as the irreversible instruction it is.

Step 1: Give Claude the source data

Attach the raw export to the conversation and state the accrual you want, in one message. Claude reads the file directly, so you do not need to clean it up first. Say what the accrual is, which period it belongs to, and how the numbers should be grouped. A useful prompt names all three:
The last sentence matters. Without it Claude may go straight to looking up accounts and posting, and you want to see the arithmetic first. Check what comes back against something you already know. A department total that is an order of magnitude off, a grand total that does not tie to the export’s own footer, or a department you do not recognize all point at a misread file rather than a bad accrual. Ask Claude to show its grouping if the totals look wrong:
Resolve any disagreement here, while the numbers are still just text in a conversation. Every later step assumes these figures are the ones you want in the ledger.

Step 2: Look up the account and company IDs

DualEntry records reference accounts and companies by numeric ID, not by name, so Claude has to resolve those before it can build the entry. Ask it to look them up rather than supplying IDs yourself.
Claude calls search_entities for each name and list_companies for the company. A returned account looks like this:
Read the account_type and number on what comes back, not just the name. Chart of accounts naming drifts, and several similarly named accounts often exist. If search_entities returns more than one plausible match, tell Claude which account number is correct instead of letting it choose. If a search returns nothing, the account does not exist under that name in your chart of accounts. Create it in DualEntry, then ask Claude to search again. Do not let it substitute a near match: an accrual posted to the wrong liability account is harder to find later than one that failed to post at all. Confirm the company too. Organizations with multiple entities frequently have similar company names, and the company ID decides which entity’s books the accrual lands in.

Step 3: Have Claude show the entry before it posts

Ask for the journal entry as a table before it goes anywhere near the ledger. This is the review step, and it is the last point at which a mistake costs nothing.
Check four things in what comes back:
  • The entry balances. Total debits equal total credits. DualEntry rejects an unbalanced entry, but catching it here saves a round trip.
  • The debits and credits sit on the right sides. An expense accrual debits the expense accounts and credits the accrued liability. A reversed pair still balances, so the ledger will accept it.
  • The account IDs match the ones you confirmed. Compare against Step 2 rather than trusting the names in the table.
  • The date is the period end you intended. A posting date of today lands the accrual in the wrong period.
Then decide the reversal. Most accruals should reverse on the first day of the following period, which DualEntry can create for you as part of the same save:
Passing a reversal date creates both halves in one operation, so the reversal cannot be forgotten next period. DualEntry adds it as a second transaction on the same journal entry, dated the reversal date, with the debits and credits flipped and a Reversal: memo prefix, rather than as a separate entry carrying its own number. Omit it only when the accrual is meant to stay on the books until something specific relieves it.

Step 4: Post the entry

Tell Claude to post once the table is right. It calls save_record with record_type set to journal_entry and a payload shaped like this:
Dates in the payload are ISO 8601 (YYYY-MM-DD), which is what the API accepts, even though you write them as 08/31/2026 when you talk to Claude. Claude converts them. A successful save returns two identifiers, and neither one is the number DualEntry displays on the entry:
Keep the record_id. For a journal entry it is the transaction ID: one number under two names, which come apart only on aggregate record types that span several transactions, such as intercompany journal entries. get_record_detail, get_record_history, and get_related_records therefore take the record_id exactly as the save returned it. Their parameter is spelled transaction_id and the tool description offers search_records as the place to find it, but no search is needed here, because you already hold the value. The record_number is a per-organization document sequence that nothing in this workflow needs. The number DualEntry shows on the entry comes from a third value, the journal entry’s own ID, which save_record does not return. To get it, have Claude read the entry back and use the id field on the get_record_detail response. For the save above that is 495642, which the interface shows as JE-495642, zero-padded to 6 digits when the ID is shorter. Results from search_records carry the same value ready-formatted in a reference field. Do not pass the record_number to get_record_by_number to find the entry. That tool resolves its argument as an ID first and only falls back to the document sequence, so 830 returns the journal entry whose ID is 830 if your organization has one, and yours only if it does not. Give it the display number instead, which is the form it expects: JE-495642. A failed save returns an error instead, and the record is not created. Nothing partial is written, so you can correct the problem and ask Claude to post again without cleaning anything up.

Step 5: Verify the entry landed

Confirm the posting in DualEntry rather than taking the tool response as proof, because a successful save still leaves room for the entry being right in form and wrong in substance. Check it through Claude first. A read-back addresses the entry by ID, so it cannot land on a different record, and it works the instant the save returns:
Claude calls get_record_detail with the record_id from the save response. The response carries the journal entry’s own id alongside its transaction_id, so this one call also gives you the display number. A journal entry line reads like this:
The unused side of each line comes back as null rather than zero, so a line showing "debit": null is a credit line and not a broken one. To open the entry in DualEntry itself, search for its display number, JE-495642 in this example. Expect a short delay: records are indexed for search asynchronously once the save commits, so an entry posted seconds ago may not be findable yet. Until it is indexed, a number search matches the document sequence rather than the display number, which can return a different entry with the same number. Compare what opens against the detail Claude read back, and if the two disagree you are looking at the wrong record rather than a bad post. Once the right entry opens, check the line accounts, the amounts, the posting date, and that the status reads Posted. Last, confirm the reversal, which takes a second call. get_record_detail returns only the lines of the transaction you asked about, with no reversal date and no reversal ID, so a reversal that posted correctly is still absent from that response. Do not read that absence as a missing reversal. Posting a manual reversing entry on top of one that already exists reverses the accrual twice, which is a worse outcome than the problem you were checking for. Ask Claude to search the reversal date instead:
Claude calls search_records with the reversal date as both start_date and end_date, and Reversal as the memo, which matches on partial text. DualEntry posts the reversal as a second transaction on the same journal entry rather than as a new entry with its own number, so what comes back shares the accrual’s JE-495642 reference and differs only in date, memo, and transaction_id. Identify it by the reversal date and the Reversal: memo prefix rather than by the number, and check that its flipped debits and credits match the original amounts.

Troubleshooting

Failures in this workflow typically fall into two categories: insufficient permissions or invalid references. In most cases, the tool response identifies the specific field that caused the error. If Claude reports no DualEntry tools at all, the connection dropped rather than the entry failing. Reconnect using Quickstart: DualEntry MCP Server and start again from Step 3, since nothing was posted.
Last modified on September 1, 2026