LedgerHQ
Guides

Posting Transactions

Post purchases, deposits, transfers, bill payments, and journal entries through the partner API.

LedgerHQ posting endpoints are the preferred way for external apps to create accounting activity. They create the posted ledger entry, attach bank-register activity when a bank account is involved, return the created identifiers, and protect retries with an Idempotency-Key header.

Required Headers

Authorization: Bearer mcp_at_your_token
x-organization-id: org_id
Idempotency-Key: stable-key-from-your-system
Content-Type: application/json

Use one idempotency key per logical transaction. Retrying the same request with the same key returns the original receipt. Reusing a key with different payload data returns an idempotency conflict.

Endpoints

MethodPathPurpose
POST/api/v1/purchasesSpend money from a bank, cash, credit card, or liability account
POST/api/v1/depositsReceive money into a bank, cash, asset, or clearing account
POST/api/v1/transfersMove money between two balance-sheet accounts
POST/api/v1/bill-paymentsPay an existing bill and allocate payment to the bill
POST/api/v1/journal-entriesCreate a balanced posted journal entry

Response

All posting endpoints return the same receipt shape:

{
  "data": {
    "id": "journal_entry_id",
    "resourceType": "purchase",
    "journalEntryId": "journal_entry_id",
    "bankTransactionIds": ["bank_transaction_id"],
    "status": "posted",
    "postedAt": "2026-06-08T16:00:00.000Z",
    "idempotencyKey": "stable-key-from-your-system"
  }
}

Examples

curl -X POST \
  -H "Authorization: Bearer mcp_at_your_token" \
  -H "x-organization-id: org_id" \
  -H "Idempotency-Key: ledgerhq-purchase-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "txnDate": "2026-06-08",
    "payeeName": "Office Depot",
    "sourceAccountId": "checking_gl_account_id",
    "memo": "Office supplies",
    "lines": [
      {
        "accountId": "office_supplies_expense_id",
        "description": "Paper and toner",
        "amount": 4299
      }
    ]
  }' \
  https://app.ledgerhq.pro/api/v1/purchases
curl -X POST \
  -H "Authorization: Bearer mcp_at_your_token" \
  -H "x-organization-id: org_id" \
  -H "Idempotency-Key: ledgerhq-deposit-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "txnDate": "2026-06-08",
    "receivedFromName": "Acme Client",
    "destinationAccountId": "checking_gl_account_id",
    "memo": "Client payment",
    "lines": [
      {
        "accountId": "consulting_revenue_id",
        "description": "June retainer",
        "amount": 250000
      }
    ]
  }' \
  https://app.ledgerhq.pro/api/v1/deposits
curl -X POST \
  -H "Authorization: Bearer mcp_at_your_token" \
  -H "x-organization-id: org_id" \
  -H "Idempotency-Key: ledgerhq-transfer-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "txnDate": "2026-06-08",
    "fromAccountId": "checking_gl_account_id",
    "toAccountId": "savings_gl_account_id",
    "amount": 100000,
    "memo": "Move excess cash"
  }' \
  https://app.ledgerhq.pro/api/v1/transfers
curl -X POST \
  -H "Authorization: Bearer mcp_at_your_token" \
  -H "x-organization-id: org_id" \
  -H "Idempotency-Key: ledgerhq-bill-payment-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "txnDate": "2026-06-08",
    "billId": "bill_id",
    "payFromAccountId": "checking_gl_account_id",
    "amount": 87500,
    "memo": "Vendor bill payment"
  }' \
  https://app.ledgerhq.pro/api/v1/bill-payments
curl -X POST \
  -H "Authorization: Bearer mcp_at_your_token" \
  -H "x-organization-id: org_id" \
  -H "Idempotency-Key: ledgerhq-journal-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "txnDate": "2026-06-08",
    "memo": "Owner contribution",
    "lines": [
      { "accountId": "checking_gl_account_id", "debit": 500000 },
      { "accountId": "owner_equity_id", "credit": 500000 }
    ]
  }' \
  https://app.ledgerhq.pro/api/v1/journal-entries

Use resource endpoints for normal app posting. Use journal entries when the business event truly is a journal adjustment.

Errors

Posting errors use a structured object so apps can decide whether a retry makes sense:

{
  "error": {
    "code": "PERIOD_LOCKED",
    "message": "The transaction date is in a locked accounting period.",
    "retryable": false,
    "requestId": "req_..."
  }
}

Common codes include VALIDATION_ERROR, AUTHORIZATION_FAILED, IDEMPOTENCY_CONFLICT, PERIOD_LOCKED, RESOURCE_NOT_FOUND, and POSTING_FAILED.

On this page