Documentation Index

Fetch the complete documentation index at: https://support.lusid.com/llms.txt

Use this file to discover all available pages before exploring further.

How do I create or update a transaction?

Prev Next

You can record the details of a new trade by booking a transaction in an appropriate transaction portfolio. Note the following:

  • A transaction must resolve to:

    • An instrument mastered in LUSID. This can be a security or a currency instrument.

    • A known transaction type that defines the precise economic impact; that is, the effect on your holding in that  instrument, and also potentially on holdings in other instruments in the portfolio too (for example, cash holdings).

    By default, LUSID operates a ‘data load first’ policy, so transactions are upserted and resolution failures must be handled manually as a post-process step. You can increase the level of validation to reject transactions that do not resolve to instruments, to transaction types, or both.

  • The process of booking creates an input transaction. LUSID automatically processes every input transaction into an output transaction, with extra information (where appropriate) such as realised gain/loss or a tax calculation.

  • LUSID assumes the transaction, settlement and portfolio currencies are the same, but if not, or your transaction is an exchange between two currencies, you can specify exchange rates explicitly, or look them up dynamically.

  • The total consideration of a transaction impacts LUSID’s calculation of holding cost. You can explicitly specify total consideration, gross consideration, bond interest and other numeric data points, or ask LUSID to calculate them for you.

  • A transaction impacts a holding in the underlying instrument unless you explicitly target a separate holding using sub-holding keys (SHKs).

  • LUSID has a transaction fee engine that can automatically calculate fee amounts from formulae and either capitalise or expense them.

Booking methods

You can upsert (that is, create or update) up to 10,000 transactions per call to the BatchUpsertTransactions API, specifying in the URL:

  • The scope and code of the parent portfolio.

  • A successMode of Atomic to reject all transactions in the request if one fails validation. The default mode of Partial means each transaction is validated on its own merits. Find out more about this.

In the body of the API request, specify an ephemeral ID for each transaction in the batch that can be used to track warnings and failures in the response. This can be the same as the transactionID, or different. It is not stored in LUSID.

Note: This API is recommended over UpsertTransactions because it resolves transactions to instruments using individual transaction dates rather than the generic date of the upsert operation itself, reducing the likelihood of instrument resolution failures.

Consider the following example of a transaction to purchase 10 units of BP @ £20, paying and settling in GBP in a EUR-denominated portfolio:

  • The units and transaction.Price fields are populated so LUSID can utilise the Buy transaction type to calculate gross consideration.

  • The totalConsideration.amount is set to 0 to trigger LUSID to calculate total consideration from a formula in the Buy transaction type.

  • The transaction is assigned to a Growth SHK using a custom property to segregate resulting holdings:

curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/UK/Equity/transactions/$batchUpsert?successMode=Partial'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "transactionRequest-1": {
    "transactionId": "Txn-0000001",
    "type": "Buy",
    "instrumentIdentifiers": {"Instrument/default/Figi": "BBG000C6K6G9"},
    "transactionDate": "2024-05-15T00:00:00.0000000+00:00",
    "settlementDate": "2024-05-18T00:00:00.0000000+00:00",
    "units": 10,
    "transactionPrice": {"price": 20, "type": "Price"},
    "totalConsideration": {"amount": 0, "currency": "GBP"},
    "properties": {
      "Transaction/MySHKs/Strategy": {
        "key": "Transaction/MySHKs/Strategy",
        "value": {
          "labelValue": "Growth"
        }
      }
    }
  }
}'

Note the following in the response:

  • LUSID confirms the globally-unique instrumentUid (LUID) and the instrumentScope of the underlying instrument.

  • LUSID sets the transactionStatus to Active. If you subsequently edit the transaction, this becomes Amended. See how to cancel a transaction.

  • LUSID sets the transactionCurrency to the same as the settlement currency, at an exchangeRate of 1.

  • The results of LUSID’s calculations of gross consideration and total consideration are not available. Instead, examine the output transaction.

  • We recommend checking the metadata section for transactions in a batch that were upserted but failed to resolve to instruments, to transaction types, or both. Find out more about this.

  • If you increased the level of validation, we recommend checking the failed section for transactions in a batch that were rejected for failing to resolve to instruments, to transaction types, or both.

{
  "values": {
    "transactionRequest-1": {
      "transactionId": "Txn-0000001",
      "type": "Buy",
      "instrumentIdentifiers": {
        "Instrument/default/Figi": "BBG000C6K6G9"
      },
      "instrumentScope": "default",
      "instrumentUid": "LUID_R7E12YK8",
      "transactionDate": "2024-05-15T00:00:00.0000000+00:00",
      "settlementDate": "2024-05-18T00:00:00.0000000+00:00",
      "units": 10,
      "transactionPrice": {
        "price": 20,
        "type": "Price"
      },
      "totalConsideration": {
        "amount": 0,
        "currency": "GBP"
      },
      "exchangeRate": 1,
      "transactionCurrency": "GBP",
      "properties": {
        "Transaction/MySHKs/Strategy": {
          "key": "Transaction/MySHKs/Strategy",
          "value": {
            "labelValue": "Growth"
          }
        }
      },
      "source": "default",
      "entryDateTime": "2026-08-29T10:49:57.5427260+00:00",
      "transactionStatus": "Active",
      "resolvedTransactionTypeDetails": {
        "scope": "default",
        "source": "default",
        "type": "Buy",
        "movementConditionMatches": []
      },
      "version": {
        "effectiveFrom": "2024-05-15T00:00:00.0000000+00:00",
        "asAtDate": "2026-08-29T10:49:57.5427260+00:00",
        "asAtCreated": "2026-08-29T10:49:57.5427260+00:00",
        "userIdCreated": "00u91lo2d7X42sdse2p7",
        "requestIdCreated": "2026082910-991496a2de9c4bfc9fd2119acf115f5f",
        "reasonCreated": "",
        "asAtModified": "2026-08-29T10:49:57.5427260+00:00",
        "userIdModified": "00u91lo2d7X42sdse2p7",
        "requestIdModified": "2026082910-991496a2de9c4bfc9fd2119acf115f5f",
        "reasonModified": "",
        "asAtVersionNumber": 1,
        "entityUniqueId": "1f00ed82-dc5f-467f-b8b2-ad5c0cc95b30_Txn-0000001"
      },
      "entityLinks": []
    }
  },
  "failed": {},
  "metadata": {},
  "staged": {},
  ... 
}

Navigate to Dashboard > Transactions, choose a transaction portfolio, click the Create transaction button, and follow the instructions to select a transaction type and instrument.

Note the following:

  • LUSID automatically calculates a Gross Trade Amount that you cannot override.

  • If the transaction type is set to automatically calculate other amounts (such as gross consideration, total consideration, bond interest or notional value), or to look up exchange rates from transaction to settlement and to portfolio currencies dynamically, then the relevant fields are marked with a ‘calculated value’ icon. You can override some of these fields.

More about calculated amounts.

Write a Luminesce SQL query using the Lusid.Portfolio.Txn.Writer provider and execute it from a tool such as the LUSID web app

Data fields and properties

This section supplements the API documentation and on-screen help text in the LUSID web app.

Note: The mandatory API fields assume that the transaction, settlement and portfolio currencies are the same. If not, or if you are booking a FX transaction to exchange two currencies, then you must set additional fields and properties. More information.

Fields

Fields by category

Explanation

transactionId,

transactionGroupId (optional)

A transaction must be uniquely identified in a portfolio; you can use the LUSID sequence APIs to auto-generate unique IDs. Specify transactionGroupId to optionally group this transaction with others (in the same or different portfolios) considered to represent the same economic event.

type,

source (optional)

A transaction must resolve to a known transaction type determining the precise economic impact, for example Buy or Sell. Specify source if the transaction is grouped with other types from a particular data provider in a custom source; otherwise, LUSID searches the default source. Note a transaction type is also domiciled in a scope but this is set on the parent portfolio, not the transaction. More about scopes and sources.

instrumentIdentifiers

A transaction must resolve to an instrument mastered in LUSID. Specify at least one unique instrument identifier as a three stage key (for example, Instrument/default/Figi or Instrument/default/LusidInstrumentId) and an appropriate value (for example, BBG000C6K6G9 or LUID_0000G7H5). you can specify as many more (unique and non-unique) as you like to increase the likelihood of successful instrument resolution.

transactionDate,

settlementDate

Note that:

  • If the settlement date is later, LUSID temporarily and separately classifies any cash holdings impacted by the transaction as unsettled, before merging into a core (settled) cash balance for the currency on the settlement date. More on holding types.

  • You can override the settlement date to settle some or all units explicitly.

units

Depending on the underlying instrument, this might represent a number of shares, the principle in an interest rate swap, the face value of a bond, a number of ETO contracts and so on.

transactionPrice.price,

transactionPrice.type

These fields are nominally optional but required if you want LUSID to automatically calculate gross consideration for you.

totalConsideration.amount,

totalConsideration.currency

The amount represents the total payable or receivable in settlement currency. Note the following:

  • While you can store any amount you like, total consideration in LUSID is intended to be after fees. So for a purchase transaction, this would be the trade amount payable plus fees. For a sale transaction, this would be the trade amount receivable minus fees.

  • Set this field to 0 to trigger LUSID to automatically calculate total consideration for you according to a formula.

  • Depending on the transaction type, the amount impacts the cost of the holding to which the transaction contributes.

Specify the ISO 4217 code of the settlement currency, for example GBP. Note LUSID generates one holding per instrument per settlement currency, so two transactions in the same instrument but in different settlement currencies generate two holdings.

exchangeRate,

transactionCurrency

These fields are optional. If omitted, LUSID assumes the settlement and transaction currencies are the same. If different, specify the ISO 4217 code of the transaction currency. You can specify an explicit exchange rate from transaction to settlement currency, or alternatively trigger LUSID to look up a market rate in the Quote Store for you. More information.

custodianEntries,

custodianAccountId (deprecated)

If the parent portfolio has nested custodian accounts you can assign the movements of a transaction to different custodians, so for example the units from a Buy transaction to a stock custodian and the outlay to a cash custodian. Note the second field is now deprecated but continues to function for historic transactions.

Properties

You can add properties to transactions at booking time by calling the BatchUpsertTransactions API and populating the properties collection. Alternatively, use the dedicated UpsertTransactionProperties API.

Properties may be:

  • Any number of custom properties from the Transaction domain to extend the data model.

  • Any of the available system properties to record additional information that LUSID can subsequently use in business operations, for example Transaction/default/GrossConsideration or  Transaction/default/TradeToPortfolioRate.

  • One or more sub-holding keys (SHKs) registered with the portfolio to assign the transaction to a specific holding once processed by the transaction type. If omitted, LUSID generates one holding in the portfolio per underlying instrument per settlement currency, with all transactions in that instrument in that currency contributing to the holding.

For information about updating or deleting properties using Upsert* APIs, see this article. Note there is also a dedicated DeletePropertiesFromTransaction API.

Subsequent updates

You can update an existing transaction by calling the BatchUpsertTransactions API. Providing you specify the ID of an existing transaction then the original is updated rather than a new one created.

Note LUSID stores every update as a separate record so you can see a full change history for transactions by calling the GetTransactions API with ShowCancelledTransactions=True, and examining the transactionStatus field:

  • A new (never updated) transaction has a single record with a status of Active.

  • An updated transaction has one record per update with a status of Amended, followed by an Active record with the latest information unless the transactionDate field has changed (see below).

  • A transaction has a status of Cancelled if you:

    • Explicitly cancelled the transaction.

    • Updated the transactionDate field. This is because LUSID automatically rebooks the transaction on the new transaction date.

To see exactly which fields have changed per update and compare new with previous values, call the GetTransactionHistory API.