Transactions & Entries
Transactions are the core of Crane Ledger's accounting system. Every financial event creates a transaction that affects multiple accounts through journal entries. Understanding the transaction lifecycle helps you track financial activity and maintain accurate records.
Transaction Components
Transaction Header
Every transaction has metadata that describes the financial event:
{
"id": "TXN_1234567890abcdef",
"organization_id": "ORG_1234567890abcdef",
"type": "income",
"reference_number": "INV-001",
"description": "Cash sale to customer",
"transaction_date": "2024-01-15",
"posting_date": "2024-01-15T10:30:00Z",
"status": "posted",
"total_debits": 100.00,
"total_credits": 100.00,
"currency_id": "CUR_USD",
"amount": 100.00,
"account_id": "ACT_1001",
"contact_id": "CON_1234567890abcdef"
}
Journal Entries
Each transaction contains multiple entries that affect individual accounts:
{
"entries": [
{
"id": "LED_1234567890abcdef",
"transaction_id": "TXN_1234567890abcdef",
"account_id": "ACT_1001",
"entry_type": "debit",
"amount": 100.00,
"currency_id": "CUR_USD",
"base_amount": 100.00,
"description": "Cash received",
"reference": "Check #1234"
},
{
"id": "LED_2345678901bcdef0",
"transaction_id": "TXN_1234567890abcdef",
"account_id": "ACT_4001",
"entry_type": "credit",
"amount": 100.00,
"currency_id": "CUR_USD",
"base_amount": 100.00,
"description": "Sales revenue",
"reference": "Invoice #001"
}
]
}
Transaction Lifecycle
1. Draft Stage
Transactions start as drafts for review and editing:
{
"status": "pending",
"description": "Pending cash sale",
"entries": [
{"account_id": "ACT_1001", "entry_type": "debit", "amount": 100.00},
{"account_id": "ACT_4001", "entry_type": "credit", "amount": 100.00}
]
}
Characteristics:
- Can be edited or deleted
- Don't affect account balances
- No financial impact
- Used for review and approval workflows
2. Posted Stage
Posted transactions are final and affect account balances:
{
"status": "posted",
"posting_date": "2024-01-15T10:30:00Z",
"entries": [
// Final entries with timestamps and references
]
}
Characteristics:
- Cannot be edited (only reversed)
- Update account balances immediately
- Create audit trail entries
- Appear in financial reports
3. Failed Stage
Transactions that encounter errors during processing:
{
"status": "failed",
"error_message": "Account ACT_9999 does not exist",
"error_code": "ACCOUNT_NOT_FOUND"
}
Characteristics:
- Don't affect balances
- Can be corrected and re-posted
- Maintain error history
- Require manual intervention
4. Reversed Stage
Reversed transactions correct previous entries:
{
"status": "reversed",
"original_transaction_id": "TXN_1234567890abcdef",
"reversal_date": "2024-01-20T14:15:00Z",
"reversal_reason": "Customer returned goods"
}
Characteristics:
- Create opposite entries
- Reference original transaction
- Maintain audit trail
- Can be posted or kept as draft
Transaction Types
Income Transactions
Revenue-generating activities:
// Cash sales
{
"type": "income",
"description": "Product sale",
"entries": [
{"account_id": "ACT_1001", "entry_type": "debit", "amount": 250.00}, // Cash
{"account_id": "ACT_4001", "entry_type": "credit", "amount": 250.00} // Sales Revenue
]
}
// Credit sales
{
"type": "income",
"description": "Invoice payment",
"entries": [
{"account_id": "ACT_1101", "entry_type": "debit", "amount": 500.00}, // Accounts Receivable
{"account_id": "ACT_4001", "entry_type": "credit", "amount": 500.00} // Sales Revenue
]
}
Expense Transactions
Cost-incurring activities:
// Cash payment
{
"type": "expense",
"description": "Office rent payment",
"entries": [
{"account_id": "ACT_5201", "entry_type": "debit", "amount": 1200.00}, // Rent Expense
{"account_id": "ACT_1001", "entry_type": "credit", "amount": 1200.00} // Cash
]
}
// Accrued expense
{
"type": "expense",
"description": "Monthly utilities",
"entries": [
{"account_id": "ACT_5301", "entry_type": "debit", "amount": 350.00}, // Utilities Expense
{"account_id": "ACT_2001", "entry_type": "credit", "amount": 350.00} // Accounts Payable
]
}
Transfer Transactions
Movement between accounts:
// Bank transfer
{
"type": "transfer",
"description": "Transfer to savings",
"entries": [
{"account_id": "ACT_1002", "entry_type": "debit", "amount": 5000.00}, // Savings Account
{"account_id": "ACT_1001", "entry_type": "credit", "amount": 5000.00} // Checking Account
]
}
Posting Process
Manual Posting
Post a draft transaction to make it final:
POST /organizations/{org_id}/transactions/{transaction_id}/post
Automatic Posting
Transactions can be posted immediately upon creation:
const transaction = await createTransaction({
description: "Cash sale",
entries: [...],
auto_post: true // Posts immediately
});
Batch Posting
Post multiple transactions at once:
POST /organizations/{org_id}/transactions/batch-post
{
"transaction_ids": ["TXN_123", "TXN_456", "TXN_789"]
}
Journal Entries vs Ledger Entries
Journal Entries
- Transaction-level: Group related entries
- Business context: Describe business events
- Human-readable: Include descriptions and references
- Audit trail: Complete record of financial activity
Ledger Entries
- Account-level: Individual account impacts
- Mathematical: Pure debit/credit amounts
- Balance updates: Drive account balance calculations
- Reporting: Feed financial statements
// Journal Entry (business context)
{
"transaction_id": "TXN_123",
"description": "Paid rent for January",
"reference": "Check #1234",
"entries": [
{
"account_id": "ACT_5201", // Rent Expense
"entry_type": "debit",
"amount": 1200.00,
"description": "January rent"
},
{
"account_id": "ACT_1001", // Cash
"entry_type": "credit",
"amount": 1200.00,
"description": "Check payment"
}
]
}
// Individual Ledger Entries (account impacts)
[
{
"id": "LED_456",
"account_id": "ACT_5201",
"entry_type": "debit",
"amount": 1200.00,
"balance_impact": 1200.00 // Increases expense
},
{
"id": "LED_789",
"account_id": "ACT_1001",
"entry_type": "credit",
"amount": 1200.00,
"balance_impact": -1200.00 // Decreases cash
}
]
Transaction Reversals
Full Reversal
Reverse an entire transaction:
POST /organizations/{org_id}/transactions/{transaction_id}/reverse
{
"reason": "Customer returned merchandise",
"reversal_date": "2024-01-20"
}
Creates opposite entries with reference to original transaction.
Partial Reversal
Reverse part of a transaction:
POST /organizations/{org_id}/transactions/{transaction_id}/reverse-partial
{
"entries": [
{
"account_id": "ACT_1001",
"entry_type": "credit", // Opposite of original debit
"amount": 50.00
},
{
"account_id": "ACT_4001",
"entry_type": "debit", // Opposite of original credit
"amount": 50.00
}
],
"reason": "Partial refund"
}
Adjustment Entries
Correct errors without reversing:
// Original transaction
{
"description": "Office supplies",
"entries": [
{"account_id": "ACT_5601", "entry_type": "debit", "amount": 100.00}, // Office Supplies Expense
{"account_id": "ACT_1001", "entry_type": "credit", "amount": 100.00} // Cash
]
}
// Adjustment for wrong account
{
"description": "Correct office supplies account",
"entries": [
{"account_id": "ACT_5601", "entry_type": "credit", "amount": 100.00}, // Reverse from wrong account
{"account_id": "ACT_5602", "entry_type": "debit", "amount": 100.00} // Correct account
]
}
Account Reconciliation
Bank Reconciliation Process
Match transactions to bank statements:
// 1. Start reconciliation
const reconciliation = await startReconciliation({
account_id: "ACT_1001", // Checking account
start_date: "2024-01-01",
end_date: "2024-01-31",
closing_balance: 15750.00
});
// 2. Mark transactions as reconciled
await reconcileTransactions({
reconciliation_id: reconciliation.id,
transaction_ids: ["TXN_123", "TXN_456", "TXN_789"]
});
// 3. Complete reconciliation
await completeReconciliation(reconciliation.id);
Reconciliation Status
Transactions can be:
- Not reconciled: New transactions
- Reconciled: Matched to bank statement
- Outstanding: Not yet cleared by bank
{
"transaction_id": "TXN_123",
"reconciled": true,
"reconciled_at": "2024-01-20T10:00:00Z",
"reconciliation_id": "REC_4567890abcdef"
}
Bank Statement Import
Import CSV/OFX files for automatic matching:
POST /organizations/{org_id}/accounts/{account_id}/import-statement
Content-Type: multipart/form-data
# File: bank_statement.csv
# Date,Description,Amount,Balance
# 2024-01-15,Deposit,$500.00,$15750.00
# 2024-01-16,Check #1234,-$250.00,$15500.00
Transaction Queries
Find by Account
GET /organizations/{org_id}/accounts/{account_id}/transactions
Find by Contact
GET /organizations/{org_id}/contacts/{contact_id}/transactions
Find by Date Range
GET /organizations/{org_id}/transactions?start_date=2024-01-01&end_date=2024-01-31
Find by Status
GET /organizations/{org_id}/transactions?status=posted
Advanced Filtering
GET /organizations/{org_id}/transactions?filters[type]=income&filters[amount][gte]=100&sort=-transaction_date
Multi-Currency Transactions
Foreign Currency Entries
{
"description": "EUR invoice payment",
"currency_id": "CUR_EUR",
"amount": 100.00,
"entries": [
{
"account_id": "ACT_1001", // USD Cash
"entry_type": "debit",
"amount": 110.00, // USD equivalent
"currency_rate": 1.10
},
{
"account_id": "ACT_1101", // EUR Accounts Receivable
"entry_type": "credit",
"amount": 100.00, // EUR amount
"currency_rate": 1.10
}
]
}
Exchange Rate Changes
Automatic entries for currency fluctuations:
// Invoice at 1.10: EUR 100 = USD 110
// Payment at 1.05: EUR 100 = USD 105
// Automatic currency loss entry
{
"description": "Currency exchange loss",
"entries": [
{"account_id": "ACT_5105", "entry_type": "debit", "amount": 5.00}, // Currency Loss Expense
{"account_id": "ACT_1101", "entry_type": "credit", "amount": 5.00} // Accounts Receivable adjustment
]
}
Recurring Transactions
Schedule Setup
const recurring = await createRecurringTransaction({
recurable_type: "transaction",
recurable_id: template_transaction.id,
frequency: "monthly",
interval: 1,
started_at: "2024-01-01",
auto_send: true
});
Execution Tracking
{
"recurring_id": "RCR_1234567890abcdef",
"next_execution": "2024-02-01",
"last_execution": "2024-01-01T09:00:00Z",
"executions_count": 12,
"status": "active"
}
Transaction Validation
Balance Validation
function validateTransaction(transaction) {
const debits = transaction.entries
.filter(e => e.entry_type === 'debit')
.reduce((sum, e) => sum + e.amount, 0);
const credits = transaction.entries
.filter(e => e.entry_type === 'credit')
.reduce((sum, e) => sum + e.amount, 0);
return debits === credits;
}
Account Validation
function validateEntries(entries) {
return entries.every(entry => {
const account = getAccount(entry.account_id);
return account && account.status === 'active';
});
}
Business Rule Validation
function validateBusinessRules(transaction) {
// Revenue transactions should credit revenue accounts
if (transaction.type === 'income') {
const hasRevenueCredit = transaction.entries.some(
e => e.entry_type === 'credit' &&
getAccount(e.account_id).type === 'revenue'
);
return hasRevenueCredit;
}
return true;
}
Audit Trail
Event Logging
Every transaction creates audit events:
{
"event_type": "transaction.posted",
"entity_type": "transaction",
"entity_id": "TXN_1234567890abcdef",
"before_state": null,
"after_state": { /* full transaction */ },
"changes": { /* what changed */ },
"api_key_id": "KEY_1234567890abcdef",
"timestamp": "2024-01-15T10:30:00Z"
}
Change Tracking
Track all modifications:
GET /organizations/{org_id}/events?entity_type=transaction&entity_id=TXN_123
Best Practices
Transaction Recording
- Record immediately - Enter transactions when they occur
- Use clear descriptions - Include sufficient detail for understanding
- Attach references - Link to invoices, checks, receipts
- Categorize properly - Use appropriate account codes
Reconciliation
- Reconcile monthly - Match to bank statements regularly
- Investigate differences - Resolve outstanding items promptly
- Document adjustments - Explain reconciliation adjustments
- Review cleared items - Verify transaction accuracy
Error Correction
- Use reversals for complete corrections - Maintain audit trail
- Use adjustments for partial corrections - When full reversal isn't appropriate
- Document reasons - Explain why corrections were needed
- Review patterns - Identify and fix recurring errors
Performance
- Batch similar transactions - Group routine entries
- Use recurring for regular items - Automate repetitive transactions
- Archive old transactions - Keep active set manageable
- Index key fields - Optimize query performance
Common Issues
Unbalanced Transactions
Error: "Transaction debits and credits do not balance"
Solutions:
- Verify all entries are included
- Check amounts for typos
- Ensure proper entry types (debit/credit)
Invalid Accounts
Error: "One or more accounts are invalid"
Solutions:
- Verify account IDs exist
- Check account status (not suspended)
- Ensure accounts are active
Posting Failures
Error: "Transaction could not be posted"
Solutions:
- Check account permissions
- Verify organization access
- Review business rule violations
- Check credit limits
Reconciliation Discrepancies
Issue: Bank balance doesn't match book balance
Solutions:
- Check for unrecorded transactions
- Verify outstanding checks/deposits
- Look for bank fees or interest
- Review timing differences
Transactions are the heartbeat of your accounting system. Understanding their lifecycle and proper recording ensures accurate financial reporting and compliance.
Need help?
Create a free account to access our support portal. Once signed in, use the Support tab in your dashboard to submit a support ticket — our team typically responds within 24 hours.
- ✨ For LLMs/AI assistants: Read our structured API reference