General journals
Overview
The General Ledger Journals API provides comprehensive functionality for creating, managing, and posting financial journal entries with full support for multi-dimensional accounting structures. This API supports the complete journal lifecycle from draft creation through posting and reversal.
Base URL: /general-journals
Key Features
- Multi-Dimensional Support: Full integration with financial dimensions for detailed classification
- Interactive Dimension Resolution: Smart account structure detection based on MainAccount
- Journal Lifecycle Management: Draft → Post → Reverse workflow
- Multiple Journal Types: Daily, Customer Payment, Vendor Payment, Payroll
- Fiscal Period Validation: Automatic validation against open periods
- Currency Support: Multi-currency transaction handling
Core Endpoints
1. Create Journal
Creates a new ledger journal with transactions supporting financial dimensions.
POST /general-journals
Content-Type: application/json
Request Body:
{
"ledger_journal_name_id": "a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
"currency_code": "AED",
"transactions": [
{
"voucher": "VOUCHER-2025-001",
"description": "Office supplies purchase",
"debit_amount": 1500.00,
"credit_amount": 0.00,
"currency_code": "AED",
"transaction_date": "2025-03-15T10:00:00.000Z",
"dimension_segments": [
{
"dimension_attribute_id": "00000000-0000-0000-0000-000000000001",
"value": "1100"
},
{
"dimension_attribute_id": "b2c3d4e5-f6a7-8901-2345-678901bcdef0",
"value": "ADMIN"
}
],
"offset_account_id": "9d3e3fa2-4717-4461-7511-5747365e5f67"
}
]
}
Response:
{
"id": "12345678-1234-1234-1234-123456789012",
"document_number": "GJ-2025-001",
"status": "Draft",
"created_date": "2025-03-15T10:00:00.000Z"
}
Status Codes:
200 OK- Journal created successfully400 Bad Request- Invalid data or validation errors500 Internal Server Error- Fiscal period closed or other server errors
2. Get Journal by ID
Retrieves a specific journal with all transaction details and dimension information.
GET /general-journals/{journalId}
Accept: application/json
Response:
{
"id": "12345678-1234-1234-1234-123456789012",
"document_number": "GJ-2025-001",
"name": "Daily Operations Journal",
"currency_code": "AED",
"status": "Draft",
"total_debit_amount": 1500.00,
"total_credit_amount": 1500.00,
"created_date": "2025-03-15T10:00:00.000Z",
"transactions": [
{
"id": "87654321-4321-4321-4321-210987654321",
"voucher": "VOUCHER-2025-001",
"description": "Office supplies purchase",
"debit_amount": 1500.00,
"credit_amount": 0.00,
"currency_code": "AED",
"transaction_date": "2025-03-15T10:00:00.000Z",
"account_display": "1100-ADMIN (Assets - Administration)",
"dimension_combination_id": "aabbccdd-1122-3344-5566-778899aabbcc",
"dimension_segments": [
{
"dimension_attribute_name": "MainAccount",
"value": "1100",
"display_value": "Cash and Cash Equivalents"
},
{
"dimension_attribute_name": "Department",
"value": "ADMIN",
"display_value": "Administration"
}
]
}
]
}
Status Codes:
200 OK- Journal found and returned404 Not Found- Journal with specified ID not found
3. Get All Journals
Retrieves all unposted journals with optional filtering and pagination.
GET /general-journals?status=Draft&take=50&skip=0
Accept: application/json
Query Parameters:
status(optional): Filter by journal status (Draft, Posted, Reversed)take(optional): Number of records to return (default: 100)skip(optional): Number of records to skip (default: 0)date_from(optional): Filter by creation date (ISO 8601)date_to(optional): Filter by creation date (ISO 8601)
Response:
[
{
"id": "12345678-1234-1234-1234-123456789012",
"document_number": "GJ-2025-001",
"name": "Daily Operations Journal",
"currency_code": "AED",
"status": "Draft",
"total_debit_amount": 1500.00,
"total_credit_amount": 1500.00,
"created_date": "2025-03-15T10:00:00.000Z"
}
]
4. Post Journal
Posts a journal entry, making it permanent and updating the general ledger.
PUT /general-journals/{journalId}/post
Content-Type: application/json
Response:
{
"success": true,
"posted_date": "2025-03-15T15:30:00.000Z",
"message": "Journal posted successfully"
}
Status Codes:
200 OK- Journal posted successfully400 Bad Request- Journal cannot be posted (invalid state, closed period, etc.)404 Not Found- Journal not found
5. Reverse Journal
Reverses a posted journal entry by creating a new reversal journal.
PUT /general-journals/{journalId}/reverse
Content-Type: application/json
Request Body:
{
"reason": "Correcting accounting error in March entries",
"use_existing_dates": false,
"reversal_date": "2025-03-16T00:00:00.000Z"
}
Response:
{
"reversal_journal_id": "11111111-2222-3333-4444-555555555555",
"reversal_document_number": "GJ-2025-001-REV",
"message": "Journal reversed successfully"
}
Status Codes:
200 OK- Journal reversed successfully400 Bad Request- Journal cannot be reversed (not posted, already reversed, etc.)404 Not Found- Journal not found
6. Create Draft Transaction
Adds a new draft transaction line to an existing journal.
POST /general-journals/{journalId}/transactions/draft
Content-Type: application/json
Request Body:
{
"description": "Additional office equipment",
"debit_amount": 800.00,
"credit_amount": 0.00,
"currency_code": "AED",
"transaction_date": "2025-03-15T12:00:00.000Z",
"dimension_segments": [
{
"dimension_attribute_id": "00000000-0000-0000-0000-000000000001",
"value": "1200"
},
{
"dimension_attribute_id": "b2c3d4e5-f6a7-8901-2345-678901bcdef0",
"value": "IT"
}
]
}
Response:
{
"id": "99999999-8888-7777-6666-555555555555",
"voucher": "AUTO-GENERATED-002",
"status": "Draft"
}
7. Get Posted Journals
Retrieves all successfully posted journals.
GET /general-journals/posted?take=50&skip=0
Accept: application/json
Response:
[
{
"id": "12345678-1234-1234-1234-123456789012",
"document_number": "GJ-2025-001",
"name": "Daily Operations Journal",
"currency_code": "AED",
"status": "Posted",
"posted_date": "2025-03-15T15:30:00.000Z",
"total_debit_amount": 1500.00,
"total_credit_amount": 1500.00,
"general_journal_entries": [
{
"account_display": "1100-ADMIN",
"debit_amount": 1500.00,
"credit_amount": 0.00
}
]
}
]
8. Get Journal Types
Retrieves available journal types for creating new journals.
GET /general-journals/journal-types
Accept: application/json
Response:
[
{
"id": 0,
"name": "Daily",
"purpose": "Create daily transactions in a general journal"
},
{
"id": 1,
"name": "Customer Payment",
"purpose": "Create customer payment transactions"
},
{
"id": 2,
"name": "Vendor Payment",
"purpose": "Create vendor disbursement transactions"
},
{
"id": 3,
"name": "Payroll Disbursement",
"purpose": "Create payroll disbursement transactions"
}
]
Dimension Support
Updated Transaction Structure
All journal transactions now support financial dimensions through the dimension_segments array:
{
"dimension_segments": [
{
"dimension_attribute_id": "00000000-0000-0000-0000-000000000001",
"value": "1100"
},
{
"dimension_attribute_id": "b2c3d4e5-f6a7-8901-2345-678901bcdef0",
"value": "SALES"
},
{
"dimension_attribute_id": "5a8e9e4e-0b0c-4c4c-8b8b-0a0a0a0a0a0a",
"value": "CC001"
}
]
}
Dimension Resolution Workflow
- User Entry: User enters MainAccount value (e.g., "1100")
- Structure Resolution: System resolves appropriate Account Structure
- UI Rendering: Frontend displays required dimension fields
- Value Creation: System creates dimension values on journal save
- Combination Creation: System creates immutable dimension combination
- Transaction Linking: Transaction linked to dimension combination
Integration with Resolve-and-Suggest-Segments
Before creating transactions, use the dimension combinations API to:
- Resolve the correct account structure
- Get required dimension fields for UI
- Validate dimension values interactively
See Dimension Combinations API documentation for details.
Dimension Support
Updated Transaction Structure
All journal transactions now support financial dimensions through the dimension_segments array:
{
"dimension_segments": [
{
"dimension_attribute_id": "00000000-0000-0000-0000-000000000001",
"value": "1100"
},
{
"dimension_attribute_id": "b2c3d4e5-f6a7-8901-2345-678901bcdef0",
"value": "SALES"
},
{
"dimension_attribute_id": "5a8e9e4e-0b0c-4c4c-8b8b-0a0a0a0a0a0a",
"value": "CC001"
}
]
}
Dimension Resolution Workflow
- User Entry: User enters MainAccount value (e.g., "1100")
- Structure Resolution: System resolves appropriate Account Structure
- UI Rendering: Frontend displays required dimension fields
- Value Creation: System creates dimension values on journal save
- Combination Creation: System creates immutable dimension combination
- Transaction Linking: Transaction linked to dimension combination
Integration with Resolve-and-Suggest-Segments
Before creating transactions, use the dimension combinations API to:
- Resolve the correct account structure
- Get required dimension fields for UI
- Validate dimension values interactively
See Dimension Combinations API documentation for details.
Complete Endpoint Reference
Journal Management
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /general-journals | Create new journal |
| GET | /general-journals/{id} | Get journal by ID |
| GET | /general-journals/by-id/{id} | Alternative get by ID |
| GET | /general-journals/by-document/{docNumber} | Get journal by document number |
| GET | /general-journals | Get all journals (with filters) |
| PUT | /general-journals/{id} | Update journal |
| DELETE | /general-journals/{id} | Delete journal |
Journal Lifecycle
| Method | Endpoint | Purpose |
|---|---|---|
| PUT | /general-journals/{id}/post | Post journal |
| PUT | /general-journals/{id}/reverse | Reverse posted journal |
| GET | /general-journals/posted | Get posted journals |
Transaction Management
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /general-journals/{id}/transactions | Add transaction |
| POST | /general-journals/{id}/transactions/draft | Create draft transaction |
| PUT | /general-journals/{id}/transactions/{txnId} | Update transaction |
| DELETE | /general-journals/{id}/transactions/{txnId} | Remove transaction |
| GET | /general-journals/transactions/by-document/{doc} | Get transactions by document |
Reporting & Analytics
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /general-journals/account-entries | Get all account entries |
| GET | /general-journals/journal-types | Get available journal types |
Specialized Journals
| Method | Endpoint | Purpose |
|---|---|---|
| * | /general-journals/customer-payments/* | Customer payment operations |
| * | /general-journals/vendor-payments/* | Vendor payment operations |
Error Handling
Common Error Responses
Fiscal Period Closed (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "The transaction date 2026-01-10 falls within a fiscal period that is not open."
}
Dimension Validation Error (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Validation Error",
"status": 400,
"detail": "Invalid dimension value 'INVALID_DEPT' for attribute 'Department'",
"errors": {
"dimension_segments[1].value": ["The value 'INVALID_DEPT' is not a valid Department"]
}
}
Journal Not Found (404 Not Found):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"detail": "Journal with ID '12345678-1234-1234-1234-123456789012' was not found."
}
Cannot Modify Posted Journal (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Business Rule Violation",
"status": 400,
"detail": "Cannot modify transactions on a posted journal. Use reversal instead."
}
Best Practices
1. Dimension Entry Workflow
// Step 1: User enters MainAccount
const mainAccount = "1100";
// Step 2: Call resolve-and-suggest-segments
const resolution = await resolveAndSuggestSegments({
ledger_id: ledgerId,
segment_inputs: [
{ dimension_attribute_id: mainAccountDimId, value: mainAccount }
]
});
// Step 3: Render required dimension fields
resolution.required_levels.forEach(level => {
if (level.is_mandatory) {
renderDimensionInput(level);
}
});
// Step 4: Create journal with complete dimensions
const journal = await createJournal({
transactions: [{
dimension_segments: completeDimensionSegments,
// ... other transaction data
}]
});
2. Transaction Management Best Practices
- Draft First: Create transactions as drafts, then update with complete data
- Validate Early: Use dimension resolution API before creating transactions
- Batch Operations: Add multiple transactions before posting for better performance
- Error Recovery: Implement proper error handling for fiscal period and dimension validation
3. Error Handling
- Always validate fiscal periods before posting
- Use dimension resolution API before creating transactions
- Handle dimension validation errors gracefully
- Provide clear error messages to users
4. Performance Optimization
- Use pagination for large journal lists
- Cache dimension attribute metadata
- Validate dimensions interactively, not just on save
- Batch multiple operations when possible
Testing
Complete Test Workflow
# 1. Create journal with dimensions
POST /general-journals
{
"ledger_journal_name_id": "...",
"currency_code": "AED",
"transactions": [{
"transaction_date": "2025-03-15",
"dimension_segments": [...],
...
}]
}
# 2. Add additional transaction
POST /general-journals/{id}/transactions
{
"description": "Second transaction",
"dimension_segments": [...],
...
}
# 3. Update transaction
PUT /general-journals/{id}/transactions/{txnId}
{
"description": "Updated transaction",
...
}
# 4. Post journal
PUT /general-journals/{id}/post
# 5. Verify posted status
GET /general-journals/{id}
# 6. Get account entries
GET /general-journals/account-entries?fromDate=2025-03-15
# 7. Reverse journal
PUT /general-journals/{id}/reverse
{ "reason": "Test reversal" }
# 8. Cleanup - delete draft journals
DELETE /general-journals/{draft-id}
# 9. Error scenarios
POST /general-journals
{
"transactions": [{ "transaction_date": "2026-01-15", ... }]
}
# Should fail with fiscal period error
Transaction-Level Testing
# Create draft transaction
POST /general-journals/{id}/transactions/draft
# Update with complete data
PUT /general-journals/{id}/transactions/{txnId}
{ "dimension_segments": [...], ... }
# Remove if needed
DELETE /general-journals/{id}/transactions/{txnId}
Related APIs
- Dimension Combinations API - For interactive dimension resolution
- Financial Dimensions API - For managing dimension definitions
- Accounts API - For account management and validation
- Customer Payment Journals API - Specialized customer payment handling
- Vendor Payment Journals API - Specialized vendor payment handling
Common Error Responses
Fiscal Period Closed (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "The transaction date 2026-01-10 falls within a fiscal period that is not open."
}
Dimension Validation Error (400 Bad Request):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Validation Error",
"status": 400,
"detail": "Invalid dimension value 'INVALID_DEPT' for attribute 'Department'",
"errors": {
"dimension_segments[1].value": ["The value 'INVALID_DEPT' is not a valid Department"]
}
}
Journal Not Found (404 Not Found):
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"detail": "Journal with ID '12345678-1234-1234-1234-123456789012' was not found."
}
Best Practices
1. Dimension Entry Workflow
// Step 1: User enters MainAccount
const mainAccount = "1100";
// Step 2: Call resolve-and-suggest-segments
const resolution = await resolveAndSuggestSegments({
ledger_id: ledgerId,
segment_inputs: [
{ dimension_attribute_id: mainAccountDimId, value: mainAccount }
]
});
// Step 3: Render required dimension fields
resolution.required_levels.forEach(level => {
if (level.is_mandatory) {
renderDimensionInput(level);
}
});
// Step 4: Create journal with complete dimensions
const journal = await createJournal({
transactions: [{
dimension_segments: completeDimensionSegments,
// ... other transaction data
}]
});
2. Error Handling
- Always validate fiscal periods before posting
- Use dimension resolution API before creating transactions
- Handle dimension validation errors gracefully
- Provide clear error messages to users
3. Performance Optimization
- Use pagination for large journal lists
- Cache dimension attribute metadata
- Validate dimensions interactively, not just on save
- Batch multiple operations when possible
Testing
Sample Test Workflow
# 1. Create journal (should succeed)
POST /general-journals
{
"ledger_journal_name_id": "...",
"currency_code": "AED",
"transactions": [{ "transaction_date": "2025-03-15", ... }]
}
# 2. Post journal (should succeed)
PUT /general-journals/{id}/post
# 3. Verify posted status
GET /general-journals/{id}
# 4. Reverse journal
PUT /general-journals/{id}/reverse
{ "reason": "Test reversal" }
# 5. Create journal with future date (should fail)
POST /general-journals
{
"transactions": [{ "transaction_date": "2026-01-15", ... }]
}
Related APIs
- Dimension Combinations API - For interactive dimension resolution
- Financial Dimensions API - For managing dimension definitions
- Accounts API - For account management and validation