Journal Entries
Journal entry creation endpoints
List journal entries
Credential: a company's API key or OAuth token.
Retrieves a paginated list of journal entries with optional filtering by date, account, customer, external system id, and search text.
Required Scope
journal-entries-read
query Parameters
cursorOpaque cursor from the previous response's nextCursor. Returns the rows after it, in the same order. Send the same filters and sort as the request that produced it, and do not send page. The preferred way to page through a list.
pageDeprecated: page with cursor instead. Page number (1-indexed). From 2026-12-31, a page past the first of a list with more than 10,000 matching rows is refused.
limitMaximum number of items per page
fromDateOnly include entries with a posting date on or after this date (ISO 8601). Filters je.date (bogføringsdato).
toDateOnly include entries with a posting date on or before this date (ISO 8601). Filters je.date (bogføringsdato).
documentDateFromOnly include entries with a document date on or after this date (ISO 8601). Filters je.documentDate.
documentDateToOnly include entries with a document date on or before this date (ISO 8601). Filters je.documentDate.
accountIdFilter by account ID
customerIdFilter by customer ID
supplierIdFilter by supplier ID
vendorIdDeprecated — use supplierId. Legacy alias for the supplier filter.
journalTypeFilter by journal type
journalCategoryIdOnly include entries in this journal category
statusFilter by entry status. Omit to get every status — an entry becomes PAID or PARTIALLY_PAID as it is settled, so filtering to POSTED returns only entries nothing has been paid against.
excludeReversedWhen true, leave out every entry reversed in LedgerBee together with its reversal. A reversed entry and its reversal cancel each other out, and both keep their status, so the status filter cannot do this. An entry cancelled by a reversal imported from e-conomic is not linked to it, so both stay in the list.
externalSystemIdExact-match filter on your own system's id (set via PATCH /journal-entries/:id or carried on the entry). Not unique — several entries may share one id, so expect zero or more results.
minAmountOnly include entries with an amount greater than or equal to this value (inclusive).
maxAmountOnly include entries with an amount less than or equal to this value (inclusive).
searchFree-text search in description and reference fields
sortBySort field. amount is not supported and is refused. documentDate cannot be combined with cursor, since entries without a document date have no place in its order.
sortOrderSort direction
List journal entries › Responses
Journal entries retrieved successfully
List of journal entries
totalTotal number of matching entries
limitNumber of items per page
nextCursorCursor for the next page; pass it as cursor. null on the last page, and on every page of a sort that cannot page by cursor — hasMore then says whether another page follows by page number.
hasMoreWhether more rows follow this page.
pageDeprecated: page with nextCursor instead. Current page number.
totalPagesDeprecated: page with nextCursor instead. Total number of pages.
Get a journal entry
Credential: a company's API key or OAuth token.
Retrieves a journal entry by its ID.
Required Scope
journal-entries-read
path Parameters
idJournal entry ID (UUID)
Get a journal entry › Responses
Journal entry retrieved successfully
idUnique identifier of the created journal entry
entryNumberEntry number assigned to the journal entry
dateDate of the journal entry
amountAmount of the line accountId names, in that line's account currency (currency). On a two-line entry this is the entry total. On a wider entry it is one line of several — sum lines[].functionalAmount on either side for the total.
currencyCurrency amount is denominated in — the operating currency of that first line's account.
journalTypeJournal type
journalCategoryIdID of the journal category the entry is in. A draft booked with a category keeps it. List the categories with GET /v1/journal-categories. Null when the entry has no category.
typeTransaction type
statusStatus of the journal entry
reversedByEntryIdThe id of the entry that reverses this one, or null when no reversal made in LedgerBee points at it. A reversed entry keeps its status, so this field is what says it no longer counts: it and its reversal cancel each other out. A reversal imported from e-conomic cancels its entry through opposite amounts and is not linked, so the entry it cancels reads null here.
reversalOfEntryIdOn a reversal, the id of the entry it reverses; null on every other entry. The entry named here names this one in its reversedByEntryId.
accountIdOne non-VAT line of the entry, paired with contraAccountId as a two-line summary. On a two-line entry the pair describes the whole entry. On a wider one it describes two of its lines and nothing about the rest — read lines for the full picture. Which two are picked is not part of this contract and differs by endpoint (a read takes them in posting order; the draft-booking response takes a debit and a credit), so do not infer a line's position from it.
createdAtTimestamp when the entry was created
documentDateDocument date (date on the invoice/voucher). Null when the entry was booked without one; its VAT period then follows date.
dueDateDue date of the customer or supplier invoice this entry books (YYYY-MM-DD). Null on every other entry type, on a credit note booked without one, and on an invoice posted through this API without a reference (no invoice is registered for it).
originalAmountWhat you posted, in the currency you posted it in — the document figure, before any conversion. Distinct from amount, which is denominated in the ACCOUNT currency (currency): a EUR entry against DKK accounts reports originalAmount: 200 / originalCurrency: "EUR" and amount: 1492.24 / currency: "DKK". Null on historical entries that stored no document amount.
originalCurrencyThe currency the entry was posted in: what originalAmount is denominated in, and what originalCurrencyToBaseCurrencyExchangeRate converts FROM. Present independently of originalAmount — an entry can name a currency and store no document amount, which is the historical shape, and the currency still says what its rate converts from. Null only on an entry that names no currency at all.
originalCurrencyToBaseCurrencyExchangeRateRate converting originalCurrency to the company base currency — 7.45 on a EUR entry of a DKK-based company means 1 EUR = 7.45 DKK, so originalAmount * originalCurrencyToBaseCurrencyExchangeRate is the base-currency total that lines[].functionalAmount sums to. Reported whether you supplied it on create or the platform resolved it, which is what lets you compute the difference against the rate your own settlement later used. 1 on an entry posted in the base currency, since that is the conversion that was applied and stored. Null only on historical entries that stored no rate at all.
originalCurrencyToBaseCurrencyExchangeRateDateDate the originalCurrencyToBaseCurrencyExchangeRate was captured for. Set on every posted entry, including one that stored no rate; an entry posted in your company base currency carries its own date.
descriptionDescription of the journal entry
referenceReference number
externalSystemIdYour own system's id for this entry, when set. Not unique — several entries may share one id.
contraAccountIdThe other half of the accountId pair, when the entry has a second non-VAT line. Same caveat: it is one line, not a summary of every line other than accountId.
Every line of the entry, including VAT lines the platform derived. This is the complete picture: accountId, contraAccountId, amount, currency and vatCodeId above all describe one line, or two, and nothing about the rest. Debits and credits balance across the array on functionalAmount. The order is stable for a given entry — normally the order the lines were posted in — but match lines by account rather than by position, and use vatSourceLineIndex to link a VAT line to its source.
customerIdCustomer ID if applicable
supplierIdSupplier ID if applicable
vatCodeIdVAT/Tax code on the line accountId names, if it has one. Lines can carry different codes — read lines[].vatCodeId for the per-line codes.
tagIdsTag IDs attached to the entry as a whole. Per-line dimensions are on lines[].tagIds.
documentRefsDocument IDs attached to the entry
Notes on the posted entry, as codes. Present only when there is one. JOURNAL_ENTRY_YEAR_END_ACCOUNT_POSTED: the entry has a line on the company year-end account and every other line is on a balance-sheet account; details.accountId names the account. An entry with a line there and an income or expense line is refused with 400 JOURNAL_ENTRY_YEAR_END_ACCOUNT_RESULT_LINE.
exchangeRateDeprecated — use originalCurrencyToBaseCurrencyExchangeRate, which carries the same value.
exchangeRateDateDeprecated — use originalCurrencyToBaseCurrencyExchangeRateDate, which carries the same value.
vendorIdDeprecated — use supplierId. Legacy alias, emitted with the same value.
Update a journal entry — correct the reference and/or set your external system id
Credential: a company's API key or OAuth token.
Partial update of a posted journal entry. Provide at least one of reference, externalSystemId.
reference corrects the reference on a CUSTOMER_INVOICE / CUSTOMER_PAYMENT / SUPPLIER_INVOICE /
SUPPLIER_PAYMENT entry and re-runs payment ↔ invoice matching. Use this when an entry was booked
with a wrong reference and therefore never matched.
externalSystemId stores your own system's id for the entry. It is metadata: settable on any
journal type regardless of match state, and never affects matching. It is not unique — several
entries may share one id; filter GET /journal-entries?externalSystemId=... to list them.
Reference corrections apply to unmatched journal entries only. A payment that settles an invoice
carries amounts derived against that invoice (currency and original exchange rate), and which
invoice a payment settled is part of the books — neither can be edited in place. Documents with
settlement activity are rejected with 409 JOURNAL_ENTRY_REFERENCE_UPDATE_ALREADY_MATCHED.
Matched to the wrong journal entry? Reverse the entry with POST /api/v1/journal-entries/reverse
and re-book it with the correct reference via POST /api/v2/journal-entries. The reversal keeps
the audit trail intact, and the re-booked entry derives its settlement amounts against the
correct invoice.
Payments: the journal entry must be UNMATCHED (not linked to an invoice). After the update the corrected reference is looked up against the counterparty's invoices — on a hit the payment is linked and the invoice status recomputed (OPEN → PARTIALLY_PAID / PAID). On a miss the payment stays unmatched and can be corrected again.
Invoices: the invoice must have no settlement activity (no applied payments or linked credit notes). The invoice number is updated and any payments already waiting on the corrected number are matched in the same transaction. A 409 is returned when the invoice is already settled against, or when another invoice for the same counterparty already uses the new number.
Reference corrections on reversed entries and other journal types are rejected with 400.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Update a journal entry — correct the reference and/or set your external system id › Request Body
referenceCorrected reference. For invoices this is the invoice number (the anchor is renumbered with it); for payments it is the invoice number the payment settles. Only unmatched entries of the four entity document types accept a reference correction.
externalSystemIdYour own system's id for this journal entry. Settable on any journal type regardless of match state. Not unique — several entries may carry the same id (e.g. one partner document booked as several entries); filter GET /journal-entries by externalSystemId to find all of them. null clears the value; omitting the field keeps it. reference does not accept null — it is a matching key, not clearable metadata.
Update a journal entry — correct the reference and/or set your external system id › Responses
Journal entry updated.
idJournal entry ID.
referenceThe reference after the update.
externalSystemIdThe external system id after the update.
Get attachments for a journal entry
Credential: a company's API key or OAuth token.
Retrieves all attachments/documents associated with a journal entry.
Required Scope
journal-entries-read
path Parameters
idJournal entry ID (UUID)
Get attachments for a journal entry › Responses
Attachments retrieved successfully
journalEntryIdJournal entry ID the attachments belong to
List of attachments
Add a document to a journal entry
Credential: a company's API key or OAuth token.
Uploads a file and attaches it to a posted journal entry — a receipt or an invoice that arrived after the entry was booked.
Send the file as the multipart form field file: PDF, JPEG or PNG, up to 10 MB. When the part is sent as
application/octet-stream, the type is taken from the file name's extension. The content must match the
type, or the upload is rejected with 400 DOCUMENT_UPLOAD_INVALID_FILE_TYPE. A file over 10 MB is rejected
with 413.
Attaching a document changes no amounts, so it is allowed when the entry's accounting period is closed. When the entry is reconciled to a card transaction, the receipt is also sent to the card provider.
The response carries the new document id; pass it to
DELETE /api/v1/journal-entries/{id}/attachments/{documentId} to take the document off again.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Add a document to a journal entry › Request Body
fileThe document: PDF, JPEG or PNG, up to 10 MB.
Add a document to a journal entry › Responses
Document attached
idID of the new attachment/document. Pass it to the remove endpoint to take the document off again.
journalEntryIdJournal entry ID the attachment was added to
Remove a document from a journal entry
Credential: a company's API key or OAuth token.
Takes a document off a posted journal entry — one attached by mistake. The document is not deleted: it returns to the inbox, unless another journal entry or draft still uses it.
Removing a document changes no amounts, so it is allowed when the entry's accounting period is closed. A receipt already sent to the card provider stays there; the removal applies in LedgerBee only.
Returns 404 JOURNAL_ENTRY_DOCUMENT_NOT_ATTACHED when the document is not attached to the entry.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID (UUID)
documentIdDocument ID (UUID), as listed by GET /api/v1/journal-entries/{id}/attachments
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Remove a document from a journal entry › Responses
Document removed from the journal entry
Preview a correction without posting it
Credential: a company's API key or OAuth token.
Runs the correction for real inside a transaction and rolls it back, so the response is what the entries would actually look like rather than a re-derivation of them. Nothing is posted and nothing is left behind.
The response carries the reversal, and — for reverseAndCorrect and reclassify — the replacement
entry beside it. A reclassify preview also returns the original for comparison and marks each
changed line with isChanged.
Every eligibility rule the real correction applies is applied here too, so a preview that returns 400 tells you the correction would be refused, and why.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Preview a correction without posting it › Request Body
correctionTypeWhich correction to preview.
correctionDate^\d{4}-\d{2}-\d{2}$Date the correction posts on (YYYY-MM-DD). When omitted, the correction is dated to the original entry so the pair lands in the same period. Must fall in an open posting period.
reasonFree-text reason appended to the correction description for audit purposes.
Line changes to preview (max 100). Required for reclassify, ignored by the other two types.
Preview a correction without posting it › Responses
Preview produced. Nothing was posted.
The reversal that would neutralise the original.
The entry as it stands today, for comparison. Present on a reclassification preview.
The replacement entry. Absent for reverseOnly, which posts no replacement.
Move postings to different accounts, keeping the document intact
Credential: a company's API key or OAuth token.
Reverses the original and posts a replacement in one transaction, with the named lines on their new accounts and every other line copied unchanged. Both entries stay on the books, so the trail shows the error and the fix.
The invoice anchor survives: an invoice reclassified this way stays payable, on the same anchor, for the same amount, and its settlements and credit-note links are carried onto the replacement. That is what makes this the right verb for a mis-coded expense or a wrong VAT code on a document the counterparty already holds.
newVatCodeId re-splits the line's gross amount, so the net posted to the account moves even though
the document total does not. Preview it first if that matters.
A line can move only to an account whose currency equals the line's accountCurrency. A move to an
account in another currency is refused with 400
JOURNAL_ENTRY_RECLASSIFY_TARGET_ACCOUNT_CURRENCY_MISMATCH, and nothing is posted.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Move postings to different accounts, keeping the document intact › Request Body
The lines to move (1-100). Lines not listed are copied to the replacement entry unchanged.
correctionDate^\d{4}-\d{2}-\d{2}$Date the correction posts on (YYYY-MM-DD). When omitted, the correction is dated to the original entry so the pair lands in the same period. Must fall in an open posting period.
reasonFree-text reason appended to the correction description for audit purposes.
Move postings to different accounts, keeping the document intact › Responses
Reversal and reclassified replacement posted
reversalIdUnique identifier of the posted reversal of the original entry.
newEntryIdUnique identifier of the posted replacement entry carrying the new account and VAT coding.
Notes on the replacement entry, as codes. Present only when there is one: JOURNAL_ENTRY_YEAR_END_ACCOUNT_POSTED when it has a line on the company year-end account and every other line is on a balance-sheet account. A replacement with a line there and an income or expense line is refused with 400 JOURNAL_ENTRY_YEAR_END_ACCOUNT_RESULT_LINE.
Rebuild the entry a reversal undid, as a draft
Credential: a company's API key or OAuth token.
A reversal cannot itself be reversed. When the reversal was the mistake, this rebuilds the original as an unlocked DRAFT on its own sides, with its accounts, amounts, VAT codes, dimensions and documents.
Nothing is posted and the reversal and the original stay as they are. Review the draft through the drafts endpoints and book it; all three entries then stand and the ledger is back at the original position.
Pass the REVERSAL's id. An invoice or a supplier bill rebuilds under its own number and date. A payment
is refused with JOURNAL_ENTRY_RECREATE_UNSUPPORTED_JOURNAL_TYPE, because it would post without restoring
the invoices it settled, and an id that is no reversal with JOURNAL_ENTRY_RECREATE_SOURCE_NOT_REVERSAL.
An entry is rebuilt once: while its draft is open the call answers JOURNAL_ENTRY_HAS_PENDING_CORRECTION_DRAFT,
and once a replacement is booked JOURNAL_ENTRY_ALREADY_CORRECTED.
Required Scope
journal-entries-write
path Parameters
idID of the reversal entry (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Rebuild the entry a reversal undid, as a draft › Responses
Draft created
draftIdUnique identifier of the unlocked DRAFT rebuilding the original. Nothing is posted until the draft is booked.
originalEntryIdUnique identifier of the original entry the reversal undid.
Preview rebuilding the entry a reversal undid
Credential: a company's API key or OAuth token.
Answers which entry the reversal undid and the date a rebuilt draft would take, and refuses for the same reasons the rebuild does. Nothing is created.
Required Scope
journal-entries-write
path Parameters
idID of the reversal entry (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Preview rebuilding the entry a reversal undid › Responses
The rebuild would be accepted. Nothing was created.
originalEntryIdUnique identifier of the original entry the reversal undid, which the draft rebuilds.
draftDateThe date the draft would take (YYYY-MM-DD): the document's own date for an invoice or a supplier bill, otherwise today.
Reverse a posted entry and open a draft to re-enter it
Credential: a company's API key or OAuth token.
Posts the reversal immediately and creates an unlocked DRAFT pre-filled from the original, so the books are neutral while the replacement is being fixed. Use this when the entry is wrong in a way that needs re-keying rather than a line-for-line account swap.
Nothing replaces the original until you book the draft. Edit it through the drafts endpoints and book it; abandoning it leaves the reversal standing on its own, which is a plain reversal.
Required Scope
journal-entries-write
path Parameters
idJournal entry ID (UUID)
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Reverse a posted entry and open a draft to re-enter it › Request Body
correctionDate^\d{4}-\d{2}-\d{2}$Date the correction posts on (YYYY-MM-DD). When omitted, the correction is dated to the original entry so the pair lands in the same period. Must fall in an open posting period.
reasonFree-text reason appended to the correction description for audit purposes.
Reverse a posted entry and open a draft to re-enter it › Responses
Reversal posted and correction draft created
reversalIdUnique identifier of the posted reversal journal entry.
draftIdUnique identifier of the unlocked DRAFT holding the replacement entry. Nothing is posted from it until the draft is booked - edit it via the drafts endpoints, then book it.
Reverse posted journal entries in batch
Credential: a company's API key or OAuth token.
Atomically reverses 1–100 posted journal entries in a single transaction. The original entries are left untouched; both originals and reversals remain visible in ledger / aging / balance reports so the audit trail is preserved.
Date handling: when reversalDate is omitted, each reversal is dated to its own
original entry so the original/reversal pair lands in the same posting period. When
reversalDate is supplied it applies to every reversal in the batch.
The posting period for every reversal date must be open. Duplicate IDs in the request are de-duplicated. If any reversal fails (closed period, ineligible source entry, etc.) the whole batch rolls back and no reversals are persisted.
Required Scope
journal-entries-write
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Reverse posted journal entries in batch › Request Body
journalEntryIdsIDs of the journal entries to reverse (1–100). All reversals run in one transaction; one failure rolls back the whole batch. Duplicate IDs are de-duplicated.
reversalDateDate for every reversal posting (YYYY-MM-DD). When omitted, each reversal is dated to its own original entry so the pair lands in the same period.
reasonFree-text reason appended to every reversal description for audit purposes.
Reverse posted journal entries in batch › Responses
Reversals posted successfully
totalReversedNumber of reversals posted. Equals the count of unique IDs in the request on success.
Result rows pairing each original ID with its newly created reversal ID.
Preview reversing posted journal entries in batch
Credential: a company's API key or OAuth token.
Takes the same body as POST /api/v1/journal-entries/batch-reverse and answers whether that call would
succeed, without posting anything. The batch runs for real inside a transaction and is rolled back, so
the first refusal the batch would raise — an entry already reversed, a reversal of a reversal, a closed
posting period, an invoice whose payment is still live and not in the batch — comes back here with the
same 400 the write would answer.
On success the response lists each original entry with its entry number and the date its reversal would post on.
Required Scope
journal-entries-write
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Preview reversing posted journal entries in batch › Request Body
journalEntryIdsIDs of the journal entries to reverse (1–100). All reversals run in one transaction; one failure rolls back the whole batch. Duplicate IDs are de-duplicated.
reversalDateDate for every reversal posting (YYYY-MM-DD). When omitted, each reversal is dated to its own original entry so the pair lands in the same period.
reasonFree-text reason appended to every reversal description for audit purposes.
Preview reversing posted journal entries in batch › Responses
Preview produced. Nothing was posted.
totalReversibleNumber of reversals the batch would post. Equals the count of unique IDs in the request.
Each original entry the batch would reverse, with the date its reversal would carry.
Reverse a posted journal entry
Credential: a company's API key or OAuth token.
Reverses a single posted journal entry. Mirrors the gated app's "Reverse only, post immediately" correction option — a new POSTED journal entry is created with the original's Dr/Cr lines flipped. The original entry is left untouched; both entries remain visible in ledger / aging / balance reports so the audit trail is preserved.
Date handling: when reversalDate is omitted, the reversal is dated to the original
entry so the pair lands in the same posting period. The posting period for the
resolved date must be open.
Eligibility: the source entry must be POSTED and not already part of a correction chain that disallows further reversal. The endpoint rejects ineligible entries with 400.
Required Scope
journal-entries-write
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Reverse a posted journal entry › Request Body
journalEntryIdUUID of the posted journal entry to reverse.
reversalDateDate for the reversal posting (YYYY-MM-DD). When omitted, the reversal is dated to the original entry so it lands in the same period. Must fall in an open posting period.
reasonFree-text reason appended to the reversal description for audit purposes.
Reverse a posted journal entry › Responses
Reversal posted successfully
reversalIdUnique identifier of the posted reversal journal entry.
Preview reversing a posted journal entry
Credential: a company's API key or OAuth token.
Takes the same body as POST /api/v1/journal-entries/reverse and answers with the reversal that call
would post, without posting it. The reversal is run for real inside a transaction and rolled back, so
the response is the entry it would create and every eligibility rule applies: an entry that is already
reversed answers 400 JOURNAL_ENTRY_ALREADY_REVERSED, a reversal of a reversal 400
JOURNAL_ENTRY_CANNOT_CORRECT_REVERSAL, and a date in a closed period is refused as the write would be.
Required Scope
journal-entries-write
Headers
x-api-idempotency-keyOptional idempotency key for safely retrying mutating requests.
Preview reversing a posted journal entry › Request Body
journalEntryIdUUID of the posted journal entry to reverse.
reversalDateDate for the reversal posting (YYYY-MM-DD). When omitted, the reversal is dated to the original entry so it lands in the same period. Must fall in an open posting period.
reasonFree-text reason appended to the reversal description for audit purposes.
Preview reversing a posted journal entry › Responses
Preview produced. Nothing was posted.
The reversal that would neutralise the original.
The entry as it stands today, for comparison. Present on a reclassification preview.
The replacement entry. Absent for reverseOnly, which posts no replacement.