Skip to main content

Overview

Period closing locks past accounting periods by creating a PERIOD_CLOSE journal entry that transfers all income and expense account balances to retained earnings. This prevents modifications to closed periods and finalizes financial results.
Permission required: periods:close (to close/undo periods), reports:read (to preview)Period closing is a critical accounting control that ensures financial records remain accurate and unchanged after review.

API Endpoints

Close Period

Close the next unclosed accounting period:
POST /period-closing/close
Headers:
  x-organization-id: {organizationId}
  x-idempotency-key: {uniqueKey}
Headers:
HeaderTypeRequiredDescription
x-organization-idstringYesOrganization ID
x-idempotency-keystringYesUnique key to prevent duplicate closes
Response:
{
  "message": "Accounting period closed successfully",
  "data": {
    "periodStart": "2026-06-01T00:00:00.000Z",
    "periodEnd": "2026-06-30T00:00:00.000Z",
    "accountingPeriod": "MONTHLY",
    "journalEntryId": "je-123",
    "closedAt": "2026-07-01T10:30:00.000Z"
  }
}

Preview Period Close

Preview what will happen when period is closed:
GET /period-closing/preview
Headers:
  x-organization-id: {organizationId}
Response:
{
  "message": "Close period preview fetched successfully",
  "data": {
    "accountingPeriod": "MONTHLY",
    "periodStart": "2026-06-01T00:00:00.000Z",
    "periodEnd": "2026-06-30T00:00:00.000Z",
    "canClose": true,
    "netProfitLoss": 125000.00,
    "incomeStatement": {
      "revenue": [
        {
          "accountId": "acc-123",
          "accountName": "Interest Income",
          "accountCode": "4000",
          "debit": 0,
          "credit": 200000,
          "netAmount": 200000
        }
      ],
      "expenses": [
        {
          "accountId": "acc-456",
          "accountName": "Operating Expenses",
          "accountCode": "5000",
          "debit": 75000,
          "credit": 0,
          "netAmount": 75000
        }
      ],
      "totalRevenue": 200000,
      "totalExpenses": 75000,
      "netIncome": 125000
    },
    "balanceSheet": { ... },
    "transactions": [ ... ],
    "validations": {
      "hasWarnings": false,
      "warnings": []
    }
  }
}
If cannot close:
{
  "canClose": false,
  "reason": "No completed accounting period available to close",
  "periodStart": null,
  "periodEnd": null
}

Undo Last Period Close

Reverse the most recent period close:
POST /period-closing/undo
Headers:
  x-organization-id: {organizationId}
  x-idempotency-key: {uniqueKey}
Headers:
HeaderTypeRequiredDescription
x-organization-idstringYesOrganization ID
x-idempotency-keystringYesUnique key to prevent duplicate undo operations
Response:
{
  "message": "Latest accounting period close undone successfully",
  "data": {
    "undoneJournalEntryId": "je-123",
    "reversalJournalEntryId": "je-456",
    "periodEnd": "2026-06-30T00:00:00.000Z",
    "undoneAt": "2026-07-02T14:20:00.000Z"
  }
}
Important: Can only undo the most recent period close. Cannot undo arbitrary past periods.

How Period Closing Works

1. Period Determination

First close (no prior periods closed):
  • Finds earliest transaction date (or organization creation date if no transactions)
  • Determines period window containing that date
  • That becomes the first period to close
Subsequent closes:
  • Finds last closed period’s end date
  • Next period = period immediately following last closed period
  • Automatic sequential closing
Current period check:
  • Cannot close current period (period containing today’s date)
  • Can only close completed past periods

2. Income & Expense Analysis

For the period being closed, the system:
  1. Finds all INCOME and EXPENSE account transactions
    • Only POSTED journal entries
    • Excludes PERIOD_CLOSE entries
    • Date range: periodStart to periodEnd
  2. Calculates net balance per account
    INCOME accounts: netIncome = credit - debit
    EXPENSE accounts: netExpense = debit - credit
    
  3. Identifies non-zero accounts
    • Skips accounts with zero net balance
    • Only accounts with activity need closing entries

3. PERIOD_CLOSE Journal Entry

Creates journal entry with kind = 'PERIOD_CLOSE' that: For INCOME accounts (normal credit balance):
  • DEBIT the income account (zeros it out)
  • CREDIT Retained Earnings (increases equity)
For EXPENSE accounts (normal debit balance):
  • CREDIT the expense account (zeros it out)
  • DEBIT Retained Earnings (decreases equity)
Net effect: All income and expense accounts go to zero, and net income transfers to Retained Earnings. Example:
Period: June 1-30, 2026
Interest Income (CREDIT balance): 200,000
Operating Expenses (DEBIT balance): 75,000
Net Income: 125,000

PERIOD_CLOSE Journal Entry (June 30, 2026):
┌────────────────────────┬────────┬─────────┐
│ Account                │ Debit  │ Credit  │
├────────────────────────┼────────┼─────────┤
│ Interest Income        │ 200,000│         │ ← Zero out revenue
│ Operating Expenses     │        │  75,000 │ ← Zero out expenses
│ Retained Earnings      │        │ 125,000 │ ← Net income to equity
├────────────────────────┼────────┼─────────┤
│ TOTAL                  │ 200,000│ 200,000 │
└────────────────────────┴────────┴─────────┘
Result:
  • Interest Income balance: 0 (was 200,000)
  • Operating Expenses balance: 0 (was 75,000)
  • Retained Earnings balance: +125,000

4. Transaction Lock

After period close entry is posted: Cannot create/modify transactions with dates in closed period:
  • ❌ Cannot record deposits dated in closed month
  • ❌ Cannot edit loans from closed period
  • ❌ Cannot delete expenses from closed period
  • ❌ Cannot create manual journal entries dated in closed period
  • ❌ System validation error: “Transaction date in closed period”
Can still access closed period data:
  • ✅ View historical transactions (read-only)
  • ✅ Generate reports for closed periods
  • ✅ Export data for audits
  • ✅ See journal entries and balances
Ongoing transactions work normally:
  • ✅ Loan payments for loans originated in closed periods
  • ✅ Reports can aggregate closed + open periods

Why Close Periods

Financial integrity:
  • Prevents retroactive changes to finalized records
  • Creates immutable historical snapshots
  • Ensures reports don’t change after distribution
Accounting accuracy:
  • Transfers net income to retained earnings
  • Prepares income/expense accounts for new period
  • Resets temporary accounts to zero
Audit compliance:
  • Demonstrates internal controls over financial records
  • Provides clear period boundaries
  • Establishes audit trail
Operational benefits:
  • Peace of mind that past periods are final
  • Prevents accidental backdating
  • Stops fraudulent modifications

Accounting Period Types

Your organization’s accounting period is configured in settings:
Period TypeFrequencyExample Close Dates
MONTHLYEvery monthJan 31, Feb 28, Mar 31…
QUARTERLYEvery 3 monthsMar 31, Jun 30, Sep 30, Dec 31
YEARLYAnnuallyDec 31 (or fiscal year-end)
Sequential closing: Periods must be closed in order (cannot skip periods).

Before Closing a Period

Critical checklist - DO NOT close until complete:Transactions:
  • ✅ All deposits, withdrawals, loans recorded for period
  • ✅ All expenses and payments posted
  • ✅ No DRAFT journal entries pending
  • ✅ All loan payments processed
Reconciliation:
  • ✅ Bank accounts reconciled with bank statements
  • ✅ Member balances verified (spot-check savings accounts)
  • ✅ Loan portfolio reconciled (outstanding balances correct)
Verification:
  • ✅ Trial balance runs and balances (debits = credits)
  • ✅ Balance sheet equation holds (Assets = Liabilities + Equity)
  • ✅ No negative balances in asset/liability accounts (unless expected)
Reporting:
  • ✅ Financial statements generated (Balance Sheet, P&L)
  • ✅ Reports reviewed by treasurer/accountant
  • ✅ Unusual items investigated and documented
Approval:
  • ✅ Management/board approval obtained
  • ✅ Minutes documenting approval (if required)
Backup:
  • ✅ Database backup created
  • ✅ Financial reports archived

Closing Workflow

Recommended process:
1

Preview period close

GET /period-closing/preview
Review period dates, net income, and validations
2

Verify net income matches expectations

Compare netProfitLoss to Profit & Loss report for period
3

Check validations

Address any warnings in validations.warnings array
4

Get approval

Present preview to treasurer/management for sign-off
5

Generate idempotency key

const idempotencyKey = `period-close-${Date.now()}-${Math.random()}`;
6

Close the period

POST /period-closing/close
Headers:
  x-idempotency-key: {idempotencyKey}
7

Verify close successful

Check response contains journalEntryId and closedAt
8

Archive reports

Export and save Balance Sheet, P&L, and closing journal entry

Example: Monthly Close

Scenario: Close June 2026 Timeline:
DateAction
Jul 1Record last June transactions
Jul 2Reconcile June bank statements
Jul 3Run June trial balance (verify balanced)
Jul 3Preview period close: GET /period-closing/preview
Jul 4Generate June financial statements
Jul 4Review with treasurer, identify net income: 125,000 RWF
Jul 5Get board approval to close June
Jul 5Close June period: POST /period-closing/close
Jul 6+Continue July transactions normally
API calls:
# Preview
curl -X GET "/period-closing/preview" \
  -H "x-organization-id: org-abc123"

# Close (after approval)
curl -X POST "/period-closing/close" \
  -H "x-organization-id: org-abc123" \
  -H "x-idempotency-key: period-close-june-2026"
Result:
  • June period locked
  • Interest income account zeroed out
  • Operating expenses account zeroed out
  • Retained earnings increased by 125,000 RWF (net income)
  • Cannot modify June transactions anymore

Undoing a Period Close

Use sparingly: Only undo for critical errors. Frequent undoing indicates poor closing procedures.
When to undo:
  • Major error discovered after close (misposted transaction)
  • Audit requires adjustment to closed period
  • Bank reconciliation error found post-close
  • Incorrect period closed by mistake
Limitations:
  • ❗ Can ONLY undo the most recent period close
  • ❗ Cannot undo arbitrary past periods (e.g., if June, July, August closed, can only undo August)
  • ❗ To undo June, must first undo August, then July, then June
Procedure:
# Undo last period close
curl -X POST "/period-closing/undo" \
  -H "x-organization-id: org-abc123" \
  -H "x-idempotency-key: undo-period-close-2026-07-02"
What happens:
  1. Finds most recent PERIOD_CLOSE journal entry
  2. Marks it as REVERSED (status = ‘REVERSED’)
  3. Creates REVERSAL journal entry with opposite debits/credits
    • Original: DEBIT Interest Income, CREDIT Retained Earnings
    • Reversal: CREDIT Interest Income, DEBIT Retained Earnings
  4. Period reopens - can now modify transactions in that period
After undo:
  • Make necessary corrections
  • Re-run all reports
  • Get re-approval
  • Close period again
Best practice: Instead of undoing, create correcting entry in current period referencing past error (if error is immaterial).

Sequential Closing

Backend enforces sequential closing automatically: Correct sequence:
  1. Close January
  2. Close February
  3. Close March
  4. Close April
Cannot skip periods:
  • Close January → Close March (skipping February) ❌ NOT ALLOWED
Why sequential?
  • Financial statements build on prior periods
  • Retained earnings balance carries forward
  • Must finalize periods in chronological order
Implementation: Backend determines next unclosed period automatically:
  • If last closed = January 31, next close = February 1-28
  • If no periods closed, next close = earliest transaction period

Year-End Closing

Additional considerations for fiscal year-end:
1

Close all months in fiscal year

Ensure all 12 months closed (if calendar year: Jan-Dec)
2

Close final month

December close triggers year-end (or last month of fiscal year)
3

Generate annual statements

GET /reports/balance-sheet?asOfDate=2025-12-31
GET /reports/profit-loss?startDate=2025-01-01&endDate=2025-12-31
4

Verify retained earnings

Retained Earnings should include all net income from closed year
5

External audit (if required)

Provide auditors with annual statements and supporting schedules
6

Archive reports

Keep 7+ years per regulations (check local laws)
Note: Income and expense accounts reset to zero after each period close (monthly, quarterly, or yearly depending on your period type).

Common Errors

“No completed accounting period available to close” Cause: Current period (containing today’s date) cannot be closed. Solution: Wait until period ends. For monthly: wait until next month starts.
“User is not part of this organization” Cause: Authenticated user doesn’t have organization membership. Solution: Verify user has organization access and correct x-organization-id header.
“x-idempotency-key header is required” Cause: Missing idempotency key header. Solution: Add unique x-idempotency-key to request:
-H "x-idempotency-key: period-close-$(date +%s)"

“No closed period available to undo” Cause: Attempting to undo when no periods have been closed. Solution: Verify periods have been closed using preview endpoint.
“Last closed period has already been undone” Cause: Attempting to undo same period multiple times. Solution: Check if period already reopened. Cannot undo twice.

Best Practices

Period closing checklist:Timing:
  • ✅ Close monthly within 7 days of month-end
  • ✅ Don’t rush - complete all reconciliation first
  • ✅ Schedule consistent close date (e.g., 5th of following month)
Verification:
  • ✅ Always preview before closing (use /period-closing/preview)
  • ✅ Compare net income to Profit & Loss report
  • ✅ Get second person to verify before closing
  • ✅ Review validation warnings in preview response
Documentation:
  • ✅ Document any unusual items before closing
  • ✅ Maintain closing checklist (paper or digital)
  • ✅ Note closing in board minutes (if required)
  • ✅ Document reason if period undone
Backup:
  • ✅ Create database backup before closing each period
  • ✅ Archive financial statements immediately after close
  • ✅ Keep backups for 7+ years
Idempotency:
  • ✅ Use unique idempotency key for each close/undo
  • ✅ Format: period-close-YYYY-MM-DD-timestamp
  • ✅ Prevents accidental duplicate closes
Reopening:
  • ✅ Only undo for critical errors
  • ✅ Get management approval before undoing
  • ✅ Document reason for undo in audit trail
  • ✅ Re-close promptly after corrections

Troubleshooting

Q: Accidentally closed period too early (still have transactions to record) A: Undo immediately:
POST /period-closing/undo
Complete missing tasks, then re-close.
Q: Need to record transaction dated in closed period A: Option 1 (if critical): Undo period, add transaction, re-close Option 2 (recommended): Record in current period with note:
Description: "Correcting June expense recorded in July -
             See receipt dated June 25"

Q: Audit requires changes to closed year A: If must change closed period:
  1. Undo periods sequentially back to target period
  2. Make auditor-approved adjustments
  3. Update all affected reports
  4. Re-close all periods
  5. Document in audit report
Note: This can be tedious if many periods closed. Consider materiality before undoing multiple periods.
Q: How do I know which period will close? A: Call preview endpoint first:
GET /period-closing/preview
Response shows periodStart and periodEnd of next period to close.
Q: Can I close periods out of order? A: No. Backend enforces sequential closing. Must close periods chronologically.
Q: What happens to INCOME/EXPENSE accounts after closing? A: They are zeroed out. Balance transfers to RETAINED_EARNINGS. Accounts reset for next period.
Q: Can I undo period close from 6 months ago? A: Only if no periods closed after it. Can only undo most recent period. To undo 6 months ago, must sequentially undo all periods closed since then.

Profit & Loss Report

View net income before closing

Balance Sheet

Verify retained earnings after close

Journal Entries

View PERIOD_CLOSE entries

Monthly Closing Checklist

Complete period-end procedures