Correcting data
Fix or remove what you pushed — with full history, and never what is in use.
What you pushed wrongly, you can fix. There are three tools, and the first is usually the right one.
| You want to… | Do this |
|---|---|
| change a line's values | re-send it with the same id (import again) |
| remove a line or an opening-balance row | delete it by id |
| remove an account, dimension value or sub-ledger | delete it — only while nothing uses it |
| retire an account that has history | import it with hidden: true |
| retire an open item | re-send it with sourceDeleted: true, or send a snapshot without it |
Nothing is ever lost: every change and every deletion keeps the previous version in
history, stamped with the import (datasetId) that made it.
Fixing a line: re-send it
Lines are merged by id. Send the corrected line through
POST …/imports/general-ledger-lines with the same id and it is updated in place.
The same goes for accounts (by accountCode), dimension values and sub-ledgers (by
key) and opening balances (by id).
Deleting lines and opening-balance rows
curl -s -X POST \
https://api.lab.accountflow.com/v1/companies/$COMPANY/imports/general-ledger-lines/deletions \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "year": 2025, "ids": ["INV-2025-000123-1", "INV-2025-000123-2"] }'
Opening balances: POST …/imports/opening-balances/deletions, same body. Up to
10 000 ids per request.
You get 202 with an import of kind general_ledger_lines_deletion; poll it like
any other. When it has succeeded:
rowsDeletedsays how many lines went;result.unknownlists ids the ledger did not have. That is not an error — it makes retrying a deletion safe;- the trial balance is already recomputed, and a voucher left without lines is gone;
- you may post the same
idagain later; it starts a fresh line.
A deletion and an import of the same kind never run at the same time for one company:
the second answers 409, reason: job_in_flight.
What cannot be deleted: anything in use
Accountflow never deletes data that work in the application depends on, and it never deletes that work for you. If any id in your request is in use, the whole request is refused and nothing is deleted:
{
"type": "https://api.accountflow.com/errors/conflict",
"status": 409,
"error": "conflict",
"reason": "lines_in_use",
"detail": "1 line(s) are in use and nothing was deleted: remove the dependent work in the application first, or post a reversing line instead",
"inUse": [
{ "id": "INV-2025-000123-2", "dependencies": ["match", "comment"] }
]
}
reason |
An object is in use when… |
|---|---|
lines_in_use |
a line is matched, reconciled against the bank, commented, flagged, part of an accrual, tied to an asset, or allocated in payroll |
opening_balances_in_use |
a row has been split, itemised into open items, matched or commented |
account_in_use |
the account has lines, opening balances, matches, reconciliations, adjustments, documents, access rules or payroll mappings |
dimension_in_use |
a line or opening balance has ever referenced the value, or it has child values |
sub_ledger_in_use |
a line, open item or opening balance has ever referenced it, or it has children |
Your options when you get a 409:
- Remove the dependent work in Accountflow (undo the match, delete the comment), then send the deletion again.
- Post a reversing line instead. For a line in a period someone has already reconciled, this is usually the right accounting answer anyway.
- For accounts: hide it (
hidden: true) rather than delete it.
The check runs when you send the request. In the rare case that someone starts
working on a line between your request and its execution, the import ends failed
with the same failureReason and the same inUse list under result — and, again,
nothing was deleted.
Deleting an account, a dimension value or a sub-ledger
curl -s -X DELETE "https://api.lab.accountflow.com/v1/companies/$COMPANY/accounts/9000?year=2025" \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)"
curl -s -X DELETE https://api.lab.accountflow.com/v1/companies/$COMPANY/dimensions/DEPT-99 \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)"
curl -s -X DELETE https://api.lab.accountflow.com/v1/companies/$COMPANY/sub-ledgers/C-9999 \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)"
Each answers 202 with an import to poll, 404 if there is no such object (or no
ledger for that year), or 409 as above. year on the account delete defaults to
the current accounting year.
Not available yet
- Replacing a whole period ("this is everything for March"). Lines are merged by
id; remove what should go with a deletion. - Rolling back a whole import. Every row carries its
datasetId, so this can come; today, delete the ids you pushed. - Forcing a delete of something in use.