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

  1. Record immediately - Enter transactions when they occur
  2. Use clear descriptions - Include sufficient detail for understanding
  3. Attach references - Link to invoices, checks, receipts
  4. Categorize properly - Use appropriate account codes

Reconciliation

  1. Reconcile monthly - Match to bank statements regularly
  2. Investigate differences - Resolve outstanding items promptly
  3. Document adjustments - Explain reconciliation adjustments
  4. Review cleared items - Verify transaction accuracy

Error Correction

  1. Use reversals for complete corrections - Maintain audit trail
  2. Use adjustments for partial corrections - When full reversal isn't appropriate
  3. Document reasons - Explain why corrections were needed
  4. Review patterns - Identify and fix recurring errors

Performance

  1. Batch similar transactions - Group routine entries
  2. Use recurring for regular items - Automate repetitive transactions
  3. Archive old transactions - Keep active set manageable
  4. 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.