Skip to content

BOR API

The Book of Record API surface provides position queries, cash management, settlement, reconciliation, journal accounting, and multi-currency translation. All operations go through the sidecar on localhost:9191.

The order-book kernel handles the order-to-fill lifecycle. BOR focuses on the post-trade balance sheet: what do I hold, what cash do I have, what transactions occurred, and are my records correct.


Position Queries

GetPositions

Returns current or historical positions. The basis parameter selects the accounting view.

positions = client.bor.get_positions(
    portfolio_id="PORT-001",
    as_of_date="2026-03-27",     # optional, defaults to now
    basis="IBOR",                 # IBOR (real-time) | ABOR (settled) | PBOR (performance)
)
for p in positions:
    print(p.instrument_id, p.quantity, p.record_date, p.settlement_date)
positions, err := client.BOR.GetPositions(ctx, &bor.GetPositionsRequest{
    PortfolioID: "PORT-001",
    Basis:       bor.BasisIBOR,
})
Basis Description
IBOR Investment book of record. Real-time, trade-date positions.
ABOR Accounting book of record. Settled positions, accrual-based.
PBOR Performance book of record. For return attribution.

GetPositionHistory

Returns a time series of position snapshots for a specific instrument.

history = client.bor.get_position_history(
    portfolio_id="PORT-001",
    instrument_id="INS-01936d8a-...",
    date_range=("2026-01-01", "2026-03-27"),
)

GetPositionsByStatus

Filters positions by encumbrance status.

pledged = client.bor.get_positions_by_status(
    portfolio_id="PORT-001",
    status="Pledged",   # Available | Pledged | OnLoan | Blocked | PendingReceipt | PendingDelivery
)

GetProjectedPositions

Forward projection including expected settlements, corporate actions, and pending trades.

projected = client.bor.get_projected_positions(
    portfolio_id="PORT-001",
    forward_date="2026-04-15",
)

CreatePosition

Creates a position adjustment directly on the order-book kernel. Used by corporate action plugins to record stock splits, mergers, spin-offs, and other non-trade position changes.

client.bor.create_position(
    portfolio_id="PORT-001",
    instrument_id="INS-01936d8a-...",
    quantity=200,                     # can be negative for reductions
    record_date="2026-03-27",
    settlement_date="2026-03-29",
)

Cash Management

GetCashBalances

Returns cash balances with trade-date or settle-date views.

balances = client.bor.get_cash_balances(
    portfolio_id="PORT-001",
    currency="USD",          # optional, all currencies if omitted
    basis="IBOR",            # optional
)
for b in balances:
    print(b.currency, b.balance, b.basis)

GetCashMovements

Returns historical cash movements.

movements = client.bor.get_cash_movements(
    portfolio_id="PORT-001",
    date_range=("2026-03-01", "2026-03-27"),
    type="SETTLEMENT",   # optional: SETTLEMENT | DIVIDEND | COUPON | FEE | CONTRIBUTION | REDEMPTION
)

ProjectCashFlow

Forward projection of expected cash flows: settlements, coupons, dividends, fees, and FX.

projected = client.bor.project_cash_flow(
    portfolio_id="PORT-001",
    forward_date="2026-06-30",
)
for cf in projected:
    print(cf.date, cf.currency, cf.amount, cf.type)

Settlement

Settlement follows three transitions on the order-book kernel, each representing a handoff between operational teams.

ConfirmOrder -> SettleOrder -> ReconcileOrder
(Middle Office)  (Custodian)   (Recon Plugin)

ConfirmOrder

Middle office confirms the order details.

client.bor.confirm_order(order_id=order_id)
# Transitions order to CONFIRMED

SettleOrder

Settlement system confirms actual settlement with the custodian.

client.bor.settle_order(order_id=order_id)
# Transitions order to SETTLED

ReconcileOrder

Reconciliation plugin confirms the position matches custodian records.

client.bor.reconcile_order(order_id=order_id)
# Transitions order to RECONCILED (terminal state)

GetSettlementStatus

records = client.bor.get_settlement_status(
    portfolio_id="PORT-001",
    date_range=("2026-03-01", "2026-03-27"),
)
for r in records:
    print(r.order_id, r.status)  # PENDING | SETTLED | LATE | FAILED

GetProjectedSettlements

upcoming = client.bor.get_projected_settlements(
    portfolio_id="PORT-001",
    forward_date="2026-04-10",
)

Reconciliation

CreateReconciliation

Defines a reconciliation job using the "any vs any" pattern. Compares two data sources with configurable matching keys and tolerances.

recon_id = client.bor.create_reconciliation(
    left_source={"type": "INTERNAL", "portfolio_id": "PORT-001"},
    right_source={"type": "CUSTODIAN", "format": "MT535", "statement_id": stmt_id},
    matching_keys=["instrument_id", "quantity"],
    tolerances={"quantity": 0.01, "market_value": 100.00},
)

RunReconciliation

Executes matching and returns results.

result = client.bor.run_reconciliation(recon_id=recon_id)
# result.matched     -> 142
# result.breaks      -> [ReconciliationBreak, ...]
# result.status      -> "COMPLETED"

Break types: MATCHED, BREAK_MISSING_INTERNAL, BREAK_MISSING_EXTERNAL, BREAK_VALUE_DIFFERENCE.

IngestExternalStatement

Ingests an external statement for reconciliation.

statement_id = client.bor.ingest_external_statement(
    source="State Street",
    format="MT535",           # MT535 | MT536 | CSV | API_JSON
    data=raw_bytes,
)

Break Management

# Resolve a break with explanation
client.bor.resolve_break(
    break_id=break_id,
    resolution="Timing difference, trade settles T+2",
    notes="Custodian confirms pending receipt",
)

# Accept a break as a known difference
client.bor.accept_break(
    break_id=break_id,
    reason="Rounding difference within tolerance",
)

# Escalate a break for investigation
client.bor.escalate_break(
    break_id=break_id,
    assigned_to="USER-0055",
)

SubscribeBreaks

Real-time stream of reconciliation break events.

for event in client.bor.subscribe_breaks(portfolio_id="PORT-001"):
    print(event.break_id, event.type, event.instrument_id, event.difference)

Journal / Accounting

All journal entries enforce the double-entry invariant: total debits must equal total credits.

GetJournalEntries

entries = client.bor.get_journal_entries(
    portfolio_id="PORT-001",
    date_range=("2026-03-01", "2026-03-27"),
    basis="GAAP",            # optional: GAAP | STAT | IFRS | TAX
    account_code="4100",     # optional
)

PostJournalEntry

Manual journal entry. The kernel rejects any entry where debits and credits do not balance.

entry_id = client.bor.post_journal_entry(
    portfolio_id="PORT-001",
    date="2026-03-27",
    lines=[
        {"account_code": "1100", "debit": 150000.00, "credit": 0, "currency": "USD"},
        {"account_code": "4100", "debit": 0, "credit": 150000.00, "currency": "USD"},
    ],
    basis=["GAAP", "IFRS"],    # multi-basis: entries generated atomically for all bases
    memo="Equity purchase settlement",
)

ReverseJournalEntry

Creates a reversal entry that inverts all lines of the original.

reversal_id = client.bor.reverse_journal_entry(entry_id=entry_id)

GetTrialBalance

Aggregate account balances where total debits must equal total credits.

tb = client.bor.get_trial_balance(
    portfolio_id="PORT-001",
    date="2026-03-27",
    basis="GAAP",
)
for account in tb.accounts:
    print(account.code, account.name, account.debit_balance, account.credit_balance)
# tb.total_debits == tb.total_credits  (always true)

ConfigureChartOfAccounts

Sets up the chart of accounts with hierarchical structure.

client.bor.configure_chart_of_accounts(
    portfolio_id="PORT-001",
    accounts=[
        {"code": "1000", "name": "Assets", "type": "ASSET", "parent": None},
        {"code": "1100", "name": "Investments", "type": "ASSET", "parent": "1000"},
        {"code": "4000", "name": "Revenue", "type": "REVENUE", "parent": None},
        {"code": "4100", "name": "Realized Gains", "type": "REVENUE", "parent": "4000"},
    ],
)

Multi-Currency

SetFXRates

Loads FX rates for valuation and translation.

client.bor.set_fx_rates(rates=[
    {"base": "EUR", "quote": "USD", "rate": 1.0842, "date": "2026-03-27"},
    {"base": "GBP", "quote": "USD", "rate": 1.2631, "date": "2026-03-27"},
    {"base": "JPY", "quote": "USD", "rate": 0.006711, "date": "2026-03-27"},
])

TranslatePortfolio

Translates all positions to a reporting currency.

translations = client.bor.translate_portfolio(
    portfolio_id="PORT-001",
    target_currency="USD",
    date="2026-03-27",
)
for t in translations:
    print(t.instrument_id, t.local_value, t.translated_value, t.fx_rate)

GetFXPnL

FX P&L decomposition over a date range.

fx_pnl = client.bor.get_fx_pnl(
    portfolio_id="PORT-001",
    date_range=("2026-01-01", "2026-03-27"),
)
for entry in fx_pnl:
    print(entry.currency, entry.fx_gain_loss, entry.translation_adjustment)

Tax Lot Configuration

Tax lot selection method is configured per portfolio. The BOR records lot closings as directed by the OMS (advised by tax lot plugins). The BOR does not select lots itself.

client.bor.configure_lot_method(
    portfolio_id="PORT-001",
    method="FIFO",   # FIFO | LIFO | HIFO | LIFO | SpecificID | MinTax | MaxTax | AverageCost
)

The lot selection plugin evaluates the configured method and advises the OMS on which lots to close when processing sell orders.