CorebanqCorebanq Developer Docs
Ledgers

Journal Transactions

Journal Transactions API

The Journal Transactions API allows you to create balanced multi-entry journal transactions across multiple ledgers with automatic currency conversion to the system's base currency.

See also:

Object Relationships

Journal transactions are the primary mechanism for complex, multi-party movements of funds. They integrate into the wider ledger hierarchy as follows:

Key Rules

  • Settlement: Journal entries immediately update the Posted Balance of the target ledgers.
  • Aggregation: If a journal entry is posted to a Subledger, the change automatically cascades up to its Parent Control Ledger(s).
  • Balance Constraint: For a transaction to be committed, the sum of all debits must equal the sum of all credits when converted to the system's Local Currency (LCY).

Key Features

  • Create multi-entry journal transactions with any number of ledger entries (minimum 2)
  • Add journal entries to existing transactions or create new ones
  • Automatic balance validation in the system's base currency (LCY)
  • Support for different currencies across entries with automatic conversion
  • Flexible ledger identification (by UUID, code, or numeric ID)
  • Support for transaction metadata and custom properties
  • Automatic parent ledger balance updates
  • DirectBooking validation - journal entries are rejected on ledgers with DirectBooking=false

Endpoints

Create Journal Transaction

POST /v1/ledgers/journals

Create a balanced multi-entry journal transaction with automatic currency conversion. You can either create a new transaction or add entries to an existing one.

Adding Entries to Existing Transactions

To add journal entries to an existing transaction, include the transaction_id field in your request:

{
  "transaction_id": "70a07097-22a2-457a-b6e6-84ce7129d6ca",
  "transaction": {
    "type": "JOURNAL",
    "total_amount": 500000,
    "currency_code": "CHF",
    "description": "Additional entries for existing transaction"
  },
  "entries": [
    {
      "ledger_code": "EXPENSES-UTILITIES",
      "amount": 500000,
      "type": "debit",
      "event": "utility_expense",
      "description": "Additional utility expense"
    },
    {
      "ledger_code": "CASH-MAIN",
      "amount": 500000,
      "type": "credit",
      "event": "utility_payment",
      "description": "Additional utility payment"
    }
  ]
}

If the transaction_id is not provided or is null, a new transaction will be created.

Request Body

{
  "transaction": {
    "type": "JOURNAL",
    "total_amount": 1000000,
    "currency_code": "CHF",
    "description": "Monthly payroll expense allocation",
    "reference_id": "PAY-2023-12",
    "value_date": "2023-12-31T12:00:00Z",
    "metadata": {
      "department": "HR",
      "payment_period": "2023-12"
    }
  },
  "entries": [
    {
      "ledger_code": "EXPENSES-SALARY",
      "amount": 1000000,
      "type": "debit",
      "event": "payroll_expense",
      "description": "December 2023 payroll expenses",
      "value_date": "2023-12-31T12:00:00Z"
    },
    {
      "ledger_code": "CASH-MAIN",
      "amount": 1000000,
      "type": "credit",
      "event": "payroll_payment",
      "description": "December 2023 payroll payment",
      "value_date": "2023-12-31T12:00:00Z"
    }
  ],
  "is_internal": false
}

Response (201 Created)

All monetary amounts are returned in CcyAmtWithPrecision format (minor units as a string, with currency code and precision).

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "JOURNAL",
  "status": "completed",
  "total_amount": {
    "amount": "1000000",
    "currency": "CHF",
    "precision": 2
  },
  "currency_id": "7c0dfa3d-2a9e-4d1a-8f8f-0d8d06358334",
  "currency_code": "CHF",
  "description": "Monthly payroll expense allocation",
  "reference_id": "PAY-2023-12",
  "timestamp": "2023-12-31T12:00:01Z",
  "value_date": "2023-12-31T12:00:00Z",
  "completed_at": "2023-12-31T12:00:01Z",
  "total_debit_lcy": {
    "amount": "1000000",
    "currency": "CHF",
    "precision": 2
  },
  "total_credit_lcy": {
    "amount": "1000000",
    "currency": "CHF",
    "precision": 2
  },
  "metadata": {
    "department": "HR",
    "payment_period": "2023-12"
  },
  "created_at": "2023-12-31T12:00:01Z",
  "modified_at": "2023-12-31T12:00:01Z",
  "created_by": "1e3d0ff4-e9e3-4b6a-a3b3-4e9b97df8f34",
  "modified_by": "1e3d0ff4-e9e3-4b6a-a3b3-4e9b97df8f34",
  "active": true
}

Usage Guidelines

Multi-Currency Entries

When creating journal entries with different currencies, the system automatically calculates the Local Currency Equivalent (LCY) amount for each entry using the current exchange rates. The journal transaction will be balanced based on the LCY amounts, not the original currency amounts.

Example:

{
  "transaction": {
    "type": "JOURNAL",
    "total_amount": 1000,
    "currency_code": "CHF",
    "description": "Multi-currency journal entry"
  },
  "entries": [
    {
      "ledger_code": "EXPENSES-USD",
      "amount": 1000,
      "currency_code": "USD",
      "type": "debit",
      "event": "usd_expense",
      "description": "USD expense"
    },
    {
      "ledger_code": "CASH-EUR",
      "amount": 950,
      "currency_code": "EUR", 
      "type": "credit",
      "event": "eur_payment",
      "description": "EUR payment"
    }
  ]
}

In this example, even though 1000 USD ≠ 950 EUR in nominal terms, the transaction may be balanced if the LCY equivalents (e.g., in CHF) are equal.

Ledger Identification Options

You can identify ledgers in three different ways:

  1. UUID (highest priority): Use ledger_id with a valid UUID
  2. Ledger Code (second priority): Use ledger_code with the accounting code
  3. Numeric ID (lowest priority): Use ledger_num_id with the numeric identifier

The system will try to find the ledger in the order listed above, based on which fields are provided.

Balance Validation

The system performs the following validations:

  1. The sum of all debit entries must equal the sum of all credit entries in LCY
  2. Each ledger must have sufficient funds for debit operations (unless overdraft is enabled)
  3. All referenced ledgers must exist and be active
  4. DirectBooking Validation: Journal entries are rejected on ledgers where DirectBooking=false. This ensures that only ledgers configured for direct booking can receive journal entries.

Parent Ledger Updates

When an entry affects a ledger that has a parent, the parent's balance (and any ancestors up the hierarchy) will be automatically updated to reflect the change.

Error Codes

CodeDescriptionHTTP Status
ledger_not_foundThe specified ledger was not found404
transaction_not_foundThe specified transaction was not found404
insufficient_fundsThe ledger has insufficient funds for the debit operation400
journal_imbalanced_lcyThe journal entries don't balance in LCY400
invalid_entry_typeThe entry type is not valid (must be 'debit' or 'credit')400
invalid_ledger_entry_typeThe entry type is not valid for this ledger400
failed_to_create_transactionFailed to create the transaction500
failed_to_create_ledger_entryFailed to create a ledger entry500
failed_to_update_ledgerFailed to update a ledger's balance500
conversion_failedCurrency conversion failed500
invalid_ledger_configurationLedger configuration prevents direct booking400

On this page