# Transactions

> Solarium docs. All requests are `POST https://api.trysolarium.com/graphql/` with `Authorization: Bearer <api key>` and a JSON body `{"query": ..., "variables": ...}`. Every query and mutation takes an `organizationId` (find it with `myOrganizations`). Index of all pages: https://trysolarium.com/llms.txt

Transactions (LedgerEvents) are the core entity in Solarium. Each transaction flows through a lifecycle: created → classified → confirmed → synced. Use createLedgerEvent for manual entries, or import via bank statement. Classify with updateStagedEntry (set category + payment account), then confirm to post to the books.

## List Transactions

Returns a paginated, filterable list of ledger events. Supports status filtering, date ranges, amount ranges, account/category scoping, and full-text search.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `status` | `[String]` | No | Filter by status (needs_review, confirmed, synced, reconciled, pending, ignored) |
| `hasDocument` | `Boolean` | No | Filter by whether a receipt/document is attached |
| `sinceDays` | `Int` | No | Only return events from the last N days |
| `dateFrom` | `String` | No | Start date filter (YYYY-MM-DD) |
| `dateTo` | `String` | No | End date filter (YYYY-MM-DD) |
| `amountMin` | `String` | No | Minimum amount filter (inclusive) |
| `amountMax` | `String` | No | Maximum amount filter (inclusive) |
| `accountIds` | `[UUID]` | No | Filter by expense/income account IDs |
| `categoryIds` | `[UUID]` | No | Filter by category account IDs |
| `search` | `String` | No | Full-text search on merchant name and memo |
| `limit` | `Int` | No | Page size (default 25, max 200) |
| `offset` | `Int` | No | Number of records to skip (default 0) |
| `sortBy` | `String` | No | Field to sort by (e.g. transactionDate, functionalAmount) |
| `sortDir` | `String` | No | asc or desc (default desc) |

### Request

```graphql
query {
  listLedgerEvents(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    status: ["needs_review"]
    dateFrom: "2026-01-01"
    dateTo: "2026-06-30"
    limit: 10
  ) {
    items {
      id
      eventType
      merchantName
      functionalAmount
      functionalCurrency
      transactionDate
      status
      hasDocument
      account { id name }
      paymentAccount { id name }
    }
    totalCount
    pageSize
    offset
  }
}
```

### Response

```json
{
  "data": {
    "listLedgerEvents": {
      "items": [
        {
          "id": "b7c8d9e0-f1a2-3456-b789-cdef01234567",
          "eventType": "expense",
          "merchantName": "Staples Canada",
          "functionalAmount": "127.43",
          "functionalCurrency": "CAD",
          "transactionDate": "2026-06-18",
          "status": "needs_review",
          "hasDocument": true,
          "account": {
            "id": "d3e4f5a6-b7c8-9012-def0-123456789abc",
            "name": "Office Supplies"
          },
          "paymentAccount": {
            "id": "e4f5a6b7-c8d9-0123-ef01-23456789abcd",
            "name": "TD Visa *8821"
          }
        },
        {
          "id": "c8d9e0f1-a2b3-4567-c890-def012345678",
          "eventType": "expense",
          "merchantName": "Tim Hortons",
          "functionalAmount": "14.85",
          "functionalCurrency": "CAD",
          "transactionDate": "2026-06-17",
          "status": "needs_review",
          "hasDocument": false,
          "account": null,
          "paymentAccount": {
            "id": "e4f5a6b7-c8d9-0123-ef01-23456789abcd",
            "name": "TD Visa *8821"
          }
        }
      ],
      "totalCount": 43,
      "pageSize": 10,
      "offset": 0
    }
  }
}
```

## Get a Transaction

Returns the full detail for a single ledger event, including attached receipts, journal entry, and classification data.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID |

### Request

```graphql
query {
  getLedgerEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "b7c8d9e0-f1a2-3456-b789-cdef01234567"
  ) {
    id
    eventType
    merchantName
    functionalAmount
    functionalCurrency
    transactionDate
    status
    memo
    hasDocument
    account { id name accountType }
    paymentAccount { id name }
    category { id name }
    journalEntry { id txnDate totalAmount }
    receipts { id filename s3Key uploadedAt }
  }
}
```

### Response

```json
{
  "data": {
    "getLedgerEvent": {
      "id": "b7c8d9e0-f1a2-3456-b789-cdef01234567",
      "eventType": "expense",
      "merchantName": "Staples Canada",
      "functionalAmount": "127.43",
      "functionalCurrency": "CAD",
      "transactionDate": "2026-06-18",
      "status": "needs_review",
      "memo": "Printer paper and toner cartridges",
      "hasDocument": true,
      "account": {
        "id": "d3e4f5a6-b7c8-9012-def0-123456789abc",
        "name": "Office Supplies",
        "accountType": "expense"
      },
      "paymentAccount": {
        "id": "e4f5a6b7-c8d9-0123-ef01-23456789abcd",
        "name": "TD Visa *8821"
      },
      "category": {
        "id": "d3e4f5a6-b7c8-9012-def0-123456789abc",
        "name": "Office Supplies"
      },
      "journalEntry": null,
      "receipts": [
        {
          "id": "f0a1b2c3-d4e5-6789-a012-bcdef0123456",
          "filename": "staples-receipt-jun18.pdf",
          "s3Key": "receipts/a1b2c3d4/2026/06/staples-receipt-jun18.pdf",
          "uploadedAt": "2026-06-18T14:32:00Z"
        }
      ]
    }
  }
}
```

## Create a Transaction

Creates a new ledger event (manual entry). The event starts in needs_review status and must be classified and confirmed before it posts to the books.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `merchantName` | `String!` | Yes | Vendor / merchant name |
| `amount` | `String!` | Yes | Transaction amount (positive decimal string) |
| `transactionDate` | `String!` | Yes | Date of transaction (YYYY-MM-DD) |
| `eventType` | `String` | No | expense, income, or transfer (default expense) |
| `categoryId` | `UUID` | No | Expense/income account to categorize under |
| `paymentAccountId` | `UUID` | No | Bank/credit card account used for payment |
| `taxAmount` | `String` | No | Tax portion of the amount (single-tax, e.g. HST/GST) |
| `taxAccountId` | `UUID` | No | Tax account for the single-tax amount (e.g. HST Payable) |
| `taxCode` | `String` | No | Tax code for the single-tax amount (e.g. HST_ON) |
| `taxComponents` | `JSONString` | No | Multi-tax entry — array of { sales_tax_code, amount } (e.g. GST + PST in BC). Overrides taxAmount/taxCode; the server resolves each component's account. |

### Request

```graphql
mutation {
  createLedgerEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    merchantName: "Canada Post"
    amount: "34.95"
    transactionDate: "2026-06-20"
    eventType: "expense"
    categoryId: "a6b7c8d9-e0f1-2345-6789-abcdef012345"
    paymentAccountId: "e4f5a6b7-c8d9-0123-ef01-23456789abcd"
  ) {
    success
    eventId
  }
}
```

### Response

```json
{
  "data": {
    "createLedgerEvent": {
      "success": true,
      "eventId": "d9e0f1a2-b3c4-5678-d901-ef0123456789"
    }
  }
}
```

## Update a Transaction

Updates mutable fields on an existing ledger event. Only events in needs_review or pending status can be updated. To record a foreign-currency transaction, pass originalCurrency (and optionally chargedAmount) — see below.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID |
| `transactionDate` | `String` | No | Updated transaction date (YYYY-MM-DD) |
| `memo` | `String` | No | Updated memo / description |
| `amount` | `String` | No | Updated amount (positive decimal string). In the original currency when originalCurrency is set. |
| `eventType` | `String` | No | Updated type: expense, income, or transfer |
| `merchantName` | `String` | No | Updated vendor / merchant name |
| `originalCurrency` | `String` | No | Original transaction currency (e.g. USD). Alone, the CAD value is derived from the Bank of Canada reference rate for the transaction date. |
| `chargedAmount` | `String` | No | The actual functional-currency (CAD) amount charged. Combined with originalCurrency, derives the effective rate including any bank markup (fx_source=manual). |

### Request

```graphql
mutation {
  updateLedgerEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "b7c8d9e0-f1a2-3456-b789-cdef01234567"
    memo: "Office supplies — printer paper and toner"
    amount: "127.43"
  ) {
    success
    event {
      id
      memo
      functionalAmount
      status
    }
  }
}
```

### Response

```json
{
  "data": {
    "updateLedgerEvent": {
      "success": true,
      "event": {
        "id": "b7c8d9e0-f1a2-3456-b789-cdef01234567",
        "memo": "Office supplies — printer paper and toner",
        "functionalAmount": "127.43",
        "status": "needs_review"
      }
    }
  }
}
```

## Confirm a Transaction

Confirms a classified ledger event, posting it to the books by creating a journal entry. The event must have a category and payment account assigned before confirming.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID to confirm |

### Request

```graphql
mutation {
  confirmLedgerEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "b7c8d9e0-f1a2-3456-b789-cdef01234567"
  ) {
    success
    eventId
    journalEntryId
  }
}
```

### Response

```json
{
  "data": {
    "confirmLedgerEvent": {
      "success": true,
      "eventId": "b7c8d9e0-f1a2-3456-b789-cdef01234567",
      "journalEntryId": "a2b3c4d5-e6f7-8901-ab23-cdef45678901"
    }
  }
}
```

## Reject a Transaction

Rejects a ledger event, moving it to ignored status. Rejected events are excluded from the books and review queue.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID to reject |

### Request

```graphql
mutation {
  rejectLedgerEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "c8d9e0f1-a2b3-4567-c890-def012345678"
  ) {
    success
    eventId
  }
}
```

### Response

```json
{
  "data": {
    "rejectLedgerEvent": {
      "success": true,
      "eventId": "c8d9e0f1-a2b3-4567-c890-def012345678"
    }
  }
}
```

## Classify Transaction

Assigns classification data to a staged ledger event. Supports three modes: intent (category + payment, server builds the balanced lines — with optional single or multi-component tax), transfer (two owned accounts, no category), and raw (client sends pre-built double-entry lines). This is the primary way to prepare a transaction for confirmation.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID to classify |
| `categoryId` | `UUID` | No | Intent mode: expense or income account ID |
| `paymentId` | `UUID` | No | Intent mode: bank/credit card payment account ID |
| `taxAmount` | `String` | No | Single-tax: tax portion of the amount (e.g. HST/GST) |
| `taxAccountId` | `UUID` | No | Single-tax: tax liability account ID (e.g. HST Payable) |
| `taxCode` | `String` | No | Single-tax: tax code identifier (e.g. HST_ON, GST, exempt) |
| `taxComponents` | `JSONString` | No | Multi-tax: array of { sales_tax_code, amount } (e.g. GST + PST). Amounts are used as-is; the server resolves each component's account. Overrides taxAmount/taxCode. |
| `fromAccountId` | `UUID` | No | Transfer mode: the owned account money moves out of |
| `toAccountId` | `UUID` | No | Transfer mode: the owned account money moves into |
| `accounts` | `JSONString` | No | Raw mode: pre-built balanced lines — array of { account_id, debit, credit, description, sales_tax_code }. Must balance (total debits = total credits). |
| `qbObjectType` | `String` | No | Raw mode: the QuickBooks object type the lines represent (e.g. journal_entry, purchase, deposit). |

### Request

```graphql
mutation {
  updateStagedEntry(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "c8d9e0f1-a2b3-4567-c890-def012345678"
    categoryId: "f5a6b7c8-d9e0-1234-5678-9abcdef01234"
    paymentId: "e4f5a6b7-c8d9-0123-ef01-23456789abcd"
    taxAmount: "1.93"
    taxAccountId: "a0b1c2d3-e4f5-6789-0abc-def123456789"
    taxCode: "HST_ON"
  ) {
    success
  }
}
```

### Response

```json
{
  "data": {
    "updateStagedEntry": {
      "success": true
    }
  }
}
```

## Attach Receipt to Transaction

Attaches an uploaded receipt (image or PDF) to a ledger event. The file must already be uploaded to S3 — pass the s3Key returned from the upload endpoint.

### Arguments

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `organizationId` | `UUID!` | Yes | Organization ID |
| `eventId` | `UUID!` | Yes | Ledger event ID to attach the receipt to |
| `s3Key` | `String!` | Yes | S3 object key of the uploaded receipt file |
| `filename` | `String` | No | Original filename for display (e.g. receipt.pdf) |

### Request

```graphql
mutation {
  attachReceiptToEvent(
    organizationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    eventId: "b7c8d9e0-f1a2-3456-b789-cdef01234567"
    s3Key: "receipts/a1b2c3d4/2026/06/canadapost-shipping-label.pdf"
    filename: "canadapost-shipping-label.pdf"
  ) {
    success
    receiptId
  }
}
```

### Response

```json
{
  "data": {
    "attachReceiptToEvent": {
      "success": true,
      "receiptId": "b1c2d3e4-f5a6-7890-bcde-f01234567890"
    }
  }
}
```
