| 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)
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 }
]
}
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.