Ledgers

WhoComply ships a native double-entry ledger. Every transaction is balanced (total debits equal total credits), append-only, hash-chained, and HMAC-signed at posting time. This gives you a regulator-defensible audit trail for the funds movements that compliance reports cite.

Amounts are passed as minor-unit integers serialized as strings (e.g. "250000000" for ₦2,500,000.00 — NGN has 2 decimals). String form prevents JavaScript from losing precision on large amounts.

GETs require read scope. Mutations require write scope.

GET/tenants/{slug}/currencies

List currencies

Returns the currencies configured for the tenant. Each currency declares its minor-unit precision.

Request

GET
/tenants/{slug}/currencies
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/currencies" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": [
    { "code": "NGN", "name": "Nigerian Naira", "minor_unit_decimals": 2 },
    { "code": "USD", "name": "United States Dollar", "minor_unit_decimals": 2 }
  ]
}

POST/tenants/{slug}/ledgers

Create ledger

Create a new ledger. Each ledger holds accounts denominated in a single currency. Requires write scope.

  • Name
    name
    Type
    string
    Description

    Human-readable ledger name.

  • Name
    currency
    Type
    string
    Description

    ISO currency code. Must be configured for the tenant.

  • Name
    description
    Type
    string
    Description

    Optional description.

  • Name
    metadata
    Type
    object
    Description

    Free-form JSON metadata.

Request

POST
/tenants/{slug}/ledgers
curl -X POST "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers" \
  -H "Authorization: Bearer wc_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Wallets",
    "currency": "NGN",
    "description": "Primary Naira wallet ledger"
  }'

Response (201)

{
  "status": "ok",
  "data": {
    "id": "ldg-a1b2c3d4-...",
    "name": "Customer Wallets",
    "currency": "NGN",
    "status": "active",
    "description": "Primary Naira wallet ledger",
    "created_at": "2026-04-17T08:00:00Z"
  }
}

GET/tenants/{slug}/ledgers

List ledgers

Returns all ledgers for the tenant.

Request

GET
/tenants/{slug}/ledgers
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": [
    {
      "id": "ldg-a1b2c3d4-...",
      "name": "Customer Wallets",
      "currency": "NGN",
      "status": "active",
      "created_at": "2026-04-17T08:00:00Z"
    }
  ]
}

GET/tenants/{slug}/ledgers/{id}

Get ledger

Returns a single ledger.

Request

GET
/tenants/{slug}/ledgers/{id}
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers/{ledger_id}" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": {
    "id": "ldg-a1b2c3d4-...",
    "name": "Customer Wallets",
    "currency": "NGN",
    "status": "active",
    "description": "Primary Naira wallet ledger",
    "created_at": "2026-04-17T08:00:00Z"
  }
}

POST/tenants/{slug}/ledgers/{id}/accounts

Create account

Create an account inside a ledger. Currency is inherited from the ledger and not specified in the body. Requires write scope.

  • Name
    code
    Type
    string
    Description

    Short, tenant-unique account code (e.g. ACC-005, OPS-CASH).

  • Name
    name
    Type
    string
    Description

    Human-readable account name.

  • Name
    account_type
    Type
    string
    Description

    One of asset, liability, equity, revenue, or expense. Determines the natural balance side.

  • Name
    external_ref
    Type
    string
    Description

    Your external reference (e.g. core-banking account number) for correlation.

  • Name
    metadata
    Type
    object
    Description

    Free-form JSON metadata.

Request

POST
/tenants/{slug}/ledgers/{id}/accounts
curl -X POST "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers/{ledger_id}/accounts" \
  -H "Authorization: Bearer wc_..." \
  -H "Content-Type: application/json" \
  -d '{
    "code": "ACC-005",
    "name": "Adebayo Mustapha Wallet",
    "account_type": "liability",
    "external_ref": "090267-0012345678",
    "metadata": { "customer_id": "f1e2d3c4-..." }
  }'

Response (201)

{
  "id": "acc-x1y2z3-...",
  "ledger_id": "ldg-a1b2c3d4-...",
  "code": "ACC-005",
  "name": "Adebayo Mustapha Wallet",
  "account_type": "liability",
  "currency": "NGN",
  "external_ref": "090267-0012345678",
  "metadata": { "customer_id": "f1e2d3c4-..." },
  "is_active": true,
  "created_at": "2026-04-17T08:15:00Z"
}

GET/tenants/{slug}/ledgers/{id}/accounts

List accounts

Returns all accounts in a ledger with running balances.

Account fields

  • Name
    balance
    Type
    string
    Description

    Signed minor-unit balance, computed by natural-side - opposite-side. For asset/expense accounts that's debit_total - credit_total; for liability/equity/revenue accounts it's credit_total - debit_total. Returned as a string.

  • Name
    debit_total
    Type
    string
    Description

    Sum of all debit entries on this account, in minor units.

  • Name
    credit_total
    Type
    string
    Description

    Sum of all credit entries on this account, in minor units.

  • Name
    entry_count
    Type
    integer
    Description

    Total number of entries booked.

  • Name
    last_activity_at
    Type
    timestamp
    Description

    When the most recent entry was posted.

Request

GET
/tenants/{slug}/ledgers/{id}/accounts
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers/{ledger_id}/accounts" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": [
    {
      "id": "acc-x1y2z3-...",
      "code": "ACC-005",
      "name": "Adebayo Mustapha Wallet",
      "account_type": "liability",
      "currency": "NGN",
      "external_ref": "090267-0012345678",
      "is_active": true,
      "debit_total": "0",
      "credit_total": "250000000",
      "balance": "250000000",
      "entry_count": 1,
      "last_activity_at": "2026-04-17T09:00:00Z",
      "created_at": "2026-04-17T08:15:00Z"
    }
  ]
}

POST/tenants/{slug}/postings

Post transaction

Create a balanced double-entry transaction. The sum of debits must equal the sum of credits in minor units, or the request is rejected. Requires write scope.

Each posting is hash-chained against the previous transaction in the ledger and signed with HMAC-SHA-256, so any tampering with stored entries is detectable via the verify endpoint.

  • Name
    ledger_id
    Type
    uuid
    Description

    Ledger this posting belongs to.

  • Name
    currency
    Type
    string
    Description

    ISO currency code. Must match the ledger's currency.

  • Name
    description
    Type
    string
    Description

    Human-readable description.

  • Name
    reference
    Type
    string
    Description

    Your external reference for this transaction.

  • Name
    idempotency_key
    Type
    string
    Description

    Pass a unique key to deduplicate retries. A second request with the same key returns the original transaction.

  • Name
    narration
    Type
    string
    Description

    Free-form context, surfaced in reports.

  • Name
    metadata
    Type
    object
    Description

    Free-form JSON metadata.

  • Name
    entries
    Type
    array
    Description

    Two or more PostingEntry objects (see below).

PostingEntry

  • Name
    account_id
    Type
    uuid
    Description

    The account being debited or credited. The same account may not appear twice in one posting.

  • Name
    debit
    Type
    string
    Description

    Minor-unit amount as a string. Mutually exclusive with credit.

  • Name
    credit
    Type
    string
    Description

    Minor-unit amount as a string. Mutually exclusive with debit.

  • Name
    description
    Type
    string
    Description

    Optional line-level description.

Request

POST
/tenants/{slug}/postings
curl -X POST "https://api.whocomply.com/api/v1/tenants/kuda-mfb/postings" \
  -H "Authorization: Bearer wc_..." \
  -H "Content-Type: application/json" \
  -d '{
    "ledger_id": "ldg-a1b2c3d4-...",
    "currency": "NGN",
    "description": "Wallet funding via bank transfer",
    "reference": "TXN-2026-04-17-001",
    "idempotency_key": "deposit-001",
    "entries": [
      { "account_id": "acc-funding-...", "debit": "250000000", "description": "Funding source" },
      { "account_id": "acc-x1y2z3-...", "credit": "250000000", "description": "Customer wallet" }
    ]
  }'

Response (201)

{
  "status": "ok",
  "data": {
    "transaction": {
      "id": "post-d4e5f6g7-...",
      "ledger_id": "ldg-a1b2c3d4-...",
      "reference": "TXN-2026-04-17-001",
      "currency": "NGN",
      "amount_minor": "250000000",
      "status": "posted",
      "hash_chain_position": 142,
      "transaction_hash": "...",
      "previous_hash": "...",
      "is_immutable": true,
      "posted_at": "2026-04-17T09:00:00Z"
    },
    "entries": [
      { "id": "ent-001", "account_id": "acc-funding-...", "debit_minor": "250000000", "credit_minor": "0" },
      { "id": "ent-002", "account_id": "acc-x1y2z3-...",   "debit_minor": "0",         "credit_minor": "250000000" }
    ]
  }
}

GET/tenants/{slug}/ledgers/{id}/transactions

List transactions

Returns posted transactions in a ledger, ordered by hash-chain position.

Request

GET
/tenants/{slug}/ledgers/{id}/transactions
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/ledgers/{ledger_id}/transactions?limit=20" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": [
    {
      "id": "post-d4e5f6g7-...",
      "ledger_id": "ldg-a1b2c3d4-...",
      "reference": "TXN-2026-04-17-001",
      "currency": "NGN",
      "amount_minor": "250000000",
      "status": "posted",
      "hash_chain_position": 142,
      "posted_at": "2026-04-17T09:00:00Z"
    }
  ]
}

GET/tenants/{slug}/postings/{id}

Get transaction

Returns a single transaction with all its entries.

Request

GET
/tenants/{slug}/postings/{id}
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/postings/{posting_id}" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": {
    "transaction": {
      "id": "post-d4e5f6g7-...",
      "ledger_id": "ldg-a1b2c3d4-...",
      "reference": "TXN-2026-04-17-001",
      "currency": "NGN",
      "amount_minor": "250000000",
      "status": "posted",
      "hash_chain_position": 142,
      "posted_at": "2026-04-17T09:00:00Z"
    },
    "entries": [
      { "id": "ent-001", "account_id": "acc-funding-...", "debit_minor": "250000000", "credit_minor": "0" },
      { "id": "ent-002", "account_id": "acc-x1y2z3-...",   "debit_minor": "0",         "credit_minor": "250000000" }
    ]
  }
}

GET/tenants/{slug}/postings/{id}/verify

Verify transaction

Re-runs every cryptographic + structural check on a posted transaction. Returns a checks object covering content hash, signature, hash-chain linkage, and double-entry balance. Used in audits and dispute investigations.

  • Name
    checks.content_hash_ok
    Type
    boolean
    Description

    The recomputed hash of the posting payload matches what was stored at posting time.

  • Name
    checks.transaction_hash_ok
    Type
    boolean
    Description

    The transaction-level hash matches its expected derivation.

  • Name
    checks.signature_ok
    Type
    boolean
    Description

    HMAC signature over the transaction hash verifies against the ledger's signing key.

  • Name
    checks.chain_ok
    Type
    boolean
    Description

    The transaction's previous_hash correctly links it into the ledger's hash chain.

  • Name
    checks.double_entry_ok
    Type
    boolean
    Description

    Total debits equal total credits across all entries.

  • Name
    verified
    Type
    boolean
    Description

    true only when all checks pass.

Request

GET
/tenants/{slug}/postings/{id}/verify
curl "https://api.whocomply.com/api/v1/tenants/kuda-mfb/postings/{posting_id}/verify" \
  -H "Authorization: Bearer wc_..."

Response

{
  "status": "ok",
  "data": {
    "transaction_id": "post-d4e5f6g7-...",
    "checks": {
      "content_hash_ok": true,
      "transaction_hash_ok": true,
      "signature_ok": true,
      "chain_ok": true,
      "double_entry_ok": true
    },
    "verified": true,
    "verified_at": "2026-04-17T09:05:00Z"
  }
}

Was this page helpful?