Skip to content

NEWUnify Agents (MCP): governed AI access to finance data. Early access.See Unify Agents

FINANCE

Writing to the ledger without breaking the books

Idempotency, validation, closed periods and approvals. A practical checklist for invoice, bill and journal entry write-back to accounting systems.

By Unify Int team5 min read

  • write-back
  • accounting
  • idempotency

Reading from an accounting system is forgiving. If a read fails, you retry. If it returns stale data, the next sync fixes it.

Writing is different. A duplicate invoice goes to a real customer. A bill posted to the wrong account distorts a P&L. A journal entry in a closed period can upset an accountant's month-end. Your customers' accountants will notice, and they will blame your product.

This post is a checklist for write-back: creating and updating invoices, bills, payments and journal entries in your customers' ledgers.

1. Make every write idempotent

Networks fail mid-request. Your worker crashes after the ledger accepted the write but before you recorded the result. You retry, and now there are two invoices.

The fix is an idempotency key: a unique value per intended write, sent with the request. If the same key arrives twice, the second request returns the original result instead of creating a new record.

Shell
curl -X POST "https://api.unifyint.com/v1/finance/invoices" \
  -H "Authorization: Bearer $UNIFY_API_KEY" \
  -H "Unify-Connection-Id: conn_xro_3m9d7" \
  -H "Idempotency-Key: 7d1f0c2e-invoice-1048" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_01JC8P9X4R",
    "issue_date": "2026-11-01",
    "due_date": "2026-12-01",
    "currency": "USD",
    "line_items": [
      { "description": "Install service", "quantity": "1", "unit_amount": "450.00", "account_id": "acc_01JC7Z1H2B" }
    ]
  }'

Rules for good keys:

  • Derive the key from your own record, such as your invoice id plus an action. Random keys per attempt defeat the purpose.
  • Store the key before you send. If you crash, you retry with the same key.
  • Keep keys long enough to cover your retry window, at least a day.

Most accounting APIs don't offer native idempotency. Some offer partial protection, such as unique document numbers. Don't rely on that alone; a ledger may allow duplicate numbers or let users change them.

2. Use decimal strings for money

Floating-point numbers can't represent most decimal amounts exactly. 0.1 + 0.2 is not 0.3 in binary floating point. Over thousands of lines, rounding errors become visible differences.

Send and store amounts as decimal strings ("1931.04") or integer minor units. Convert to a decimal type in your code, never to a float.

3. Validate before you submit

Every ledger rejects bad writes, but the error messages vary from helpful to cryptic. Validating first gives you clear errors and fewer partial failures.

Check at least:

  • Accounts exist and are active. Customers deactivate accounts. A cached chart of accounts goes stale.
  • Account types fit the line. An income line on a bill, or an expense account on an invoice, is usually a mistake.
  • Tax codes exist and apply to the company's region and settings.
  • Currencies are enabled. Multi-currency is often a setting the customer must turn on.
  • Customers and vendors exist, or create them first, idempotently.
  • The period is open. See the next section.
  • Totals add up when you send both line amounts and totals.

4. Respect closed periods

Accountants close periods after month-end so the numbers stop moving. Most ledgers can lock dates; some warn, some block, some let admins override.

Your product should never quietly post into a closed period. Options:

  • Read the lock date where the platform exposes it, and refuse writes before it with a clear error.
  • Post to the next open period if your customer has agreed to that rule, and record that you did.
  • Ask a person. Surface the conflict in your product.

5. Handle concurrency

Someone may edit a record while your product updates it. QuickBooks Online uses a SyncToken for this. Other platforms use timestamps, ETags or nothing at all.

  • Read before update and send the version the platform expects.
  • On conflict, re-read and re-apply your change, or ask the user. Never overwrite blindly.
  • Prefer partial updates so you don't erase fields you didn't mean to touch.

6. Add approvals where risk is high

Not every write needs a human, but some do. Common rules:

  • Writes above an amount threshold.
  • Writes to sensitive objects, such as journal entries or vendor bank details.
  • Writes initiated by an AI agent rather than a user.
  • The first writes for a new customer, until mappings are trusted.

An approval step pauses the write, notifies a person, and proceeds only when they approve. The idempotency key ties the approval to exactly one write.

ERPs often have their own approval workflows for vendor bills and journal entries. Respect them. A bill should usually enter the ERP as pending approval, not bypass the customer's controls.

7. Keep an audit trail

When an accountant asks "who created this bill?", you need an answer. Record, for every write:

  • The actor: user, API key, workflow or agent.
  • The object and action.
  • Values before and after.
  • The request you sent and the platform's response.
  • The timestamp and idempotency key.

Make the log searchable by customer and exportable.

8. Plan for partial failures

Some operations span several calls: create a vendor, then a bill, then attach a PDF. Any step can fail.

  • Order steps so each one is safe to retry.
  • Make each step idempotent on its own.
  • Record progress so a retry resumes rather than restarts.
  • Surface stuck writes to your support team with the platform error.

9. Test against reality

Sandbox companies are clean. Real ledgers have inactive accounts, duplicate customer names, custom tax setups and years of history. Before launch:

  • Test every write path in a sandbox for each platform.
  • Test against a real, messy file with permission.
  • Test retries by killing workers mid-request.
  • Test closed periods and missing accounts on purpose.

The checklist

CheckWhy
Idempotency key per intended writeNo duplicates on retry
Decimal strings for amountsNo float rounding
Validate accounts, tax, currency, periodClear errors, fewer rejections
Respect lock datesDon't move closed books
Handle version conflictsDon't overwrite edits
Approvals for risky writesA person signs off
Audit every writeAnswer "who did this?"
Resumable multi-step writesRecover from partial failure

How Unify Int fits

The Unify Int write path is designed around this list: idempotency keys on every write, validation of accounts, tax codes, currencies and periods before submit, optional approvals, and an audit log with before-and-after values.

See Finance, the Accounting API and Permissions & Audit.

Keep reading

Get started

Connect once. Build everything else on top.

Request sandbox access, or book 30 minutes with an engineer to map your integrations.

Free sandbox access. No credit card. Reply within one business day.