---
title: "Journal Entries"
description: "Create, submit, review, approve and reverse manual journal entries, and read the workflow history behind each one."
url: "https://bareledger.app/guides/api-journals"
category: "Developers & API"
updated: "2026-10-04"
publisher: "BareLedger (Syneria Technologies OPC)"
---

# Journal Entries

> Create, submit, review, approve and reverse manual journal entries, and read the workflow history behind each one.

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET journals` | `journal.view` | Paginated list | — |
| `POST journals` | `journal.create` | Create draft entry | — |
| `GET journals/{journal}` | `journal.view` | Detail | — |
| `PATCH journals/{journal}` | `journal.create` | Edit draft | — |
| `DELETE journals/{journal}` | `journal.create` | Delete draft | — |
| `GET journals/{journal}/pdf` | `journal.view` | Stream PDF with signature block | — |
| `GET journals/{journal}/history` | `journal.view` | Workflow event history | — |
| `POST journals/{journal}/submit` | `journal.submit` | Draft → Submitted | Workflow transition |
| `POST journals/{journal}/review` | `journal.review` | Submitted → Reviewed | TOTP step-up optional/required per tenant policy |
| `POST journals/{journal}/approve` | `journal.approve` | Reviewed → Approved, auto-posts | **Posts to ledger** |
| `POST journals/{journal}/reject` | `journal.reject` | Back to Draft, history preserved | — |
| `POST journals/{journal}/reverse` | `journal.reverse` (Preparer + Full access tiers — Staff and Accountant request; Administrator/Reviewer/Approver only oversee) | Request reversal of a posted entry | Submits a mirror reversing entry into the maker-checker queue (the original stays `posted` until it is approved); TOTP required if `require_totp_for_posting` |

## Recurring journal entries (`recurring-journal-entries`)

| Method & Path | Permission | Purpose | Side effects |
|---|---|---|---|
| `GET recurring-journal-entries` | `journal.view` | List schedules | — |
| `POST recurring-journal-entries` | `journal.create` | Create schedule | Pass `source_document_id` to copy an existing entry — it must be **approved and posted** (`status = posted`), otherwise `422` on `source_document_id`; drafts and in-flight records cannot be made recurring. Dry-runs the template (rolled back) to catch bad references; computes first occurrence |
| `GET recurring-journal-entries/{schedule}` | `journal.view` | Detail + runs | — |
| `PATCH recurring-journal-entries/{schedule}` | `journal.create` | Update (partial) | Recomputes next-run if recurrence fields changed |
| `DELETE recurring-journal-entries/{schedule}` | `journal.create` | Delete (or pause if it has generated documents) | — |
| `POST recurring-journal-entries/{schedule}/pause` \| `/resume` | `journal.create` | Pause/resume | Resume recomputes next occurrence |
| `POST recurring-journal-entries/{schedule}/runs/{run}/resolve-dst` | `journal.create` | Manually resolve a DST-ambiguous occurrence | Generates the flagged entry at the given instant |


## Request/response shape (illustrative, sanitized)

```json
POST /api/v1/journals
{
  "transaction_date": "2026-08-01",
  "branch_id": "<branch-uuid>",
  "currency": "PHP",
  "lines": [
    { "account_id": "<account-uuid>", "debit": 1000.00, "credit": 0 },
    { "account_id": "<account-uuid>", "debit": 0, "credit": 1000.00 }
  ]
}
```
```json
201 Created
{
  "uuid": "<journal-uuid>",
  "document_number": null,
  "status": "draft",
  "total_debit": "1000.0000",
  "total_credit": "1000.0000"
}
```
Debits/credits are validated and totaled **server-side**; `document_number` is assigned atomically only at posting time, not at draft creation.
