Skip to main content
A custody account is the internal ledger account that receives payment funds on behalf of an event. Each payment method in the TMT Platform is linked to a custody account — when a buyer pays by bank transfer, the funds go to a specific custody account identified by custody_account.id. Custody accounts live in the custody_accounts Firestore collection. Each document tracks a running balance_available field that reflects the total amount of funds received.

How custody balances are updated

When transactions_generate processes a transaction, it writes a copy of the transaction to the custody account’s sub-collection:
custody_accounts/
  {custody_account_id}/
    transactions/
      {auto_id}    ← written by transactions_generate with amount_type: "payment"
This write fires the custody_process Firestore trigger, which increments balance_available by the transaction amount.
The amount_type field gates the custody update. transactions_generate explicitly sets amount_type = "payment" before writing to the custody sub-collection. Only documents with amount_type == "payment" trigger a balance increment. Any other value causes the trigger to return without making changes.

custody_process

A Firestore trigger that fires whenever a new document is created under custody_accounts/{idaccounts}/transactions/{idtransaction}. Trigger: onDocumentCreated("custody_accounts/{idaccounts}/transactions/{idtransaction}")

What it does

  1. Reads the newly created transaction document.
  2. Checks data.amount_type.
    • If "payment": increments balance_available on the parent custody_accounts/{idaccounts} document by data.amount, and sets date.update to the current server timestamp.
    • Any other value: exits without writing.

Trigger path parameters

ParameterDescription
idaccountsFirestore document ID of the custody account
idtransactionFirestore document ID of the transaction sub-document

Fields read from the transaction document

amount_type
string
Must equal "payment" for the custody balance to be updated. Set automatically by transactions_generate.
amount
number
The payment amount that is added to balance_available.

Fields written to the custody account document

balance_available
number
Incremented by amount using Firestore’s FieldValue.increment() — safe for concurrent writes.
date.update
Timestamp
Set to the server timestamp at the time of the update.

Example

A transaction of USD 75.00 is processed through custody account cust_001:
  1. transactions_generate writes to custody_accounts/cust_001/transactions/{auto_id} with amount: 75.00 and amount_type: "payment".
  2. custody_process fires on the new document.
  3. custody_accounts/cust_001 is updated: balance_available increases by 75.00.
// Effective operation performed by custody_process
await db.collection("custody_accounts").doc("cust_001").update({
  "balance_available": FieldValue.increment(75.00),
  "date.update": Timestamp.now()
});
FieldValue.increment() is an atomic server-side operation. Multiple concurrent transactions writing to the same custody account will not produce race conditions or lost updates.

Custody account document structure

FieldTypeDescription
balance_availablenumberRunning total of all payment amounts received
date.updateTimestampLast time the balance was updated
Additional fields such as account name, account number, and associated payment method are set at custody account creation and are read (but not modified) by custody_process.

Relationship to payout distribution

Each orders_payout record references the same custody_account.id, custody_account.name, and custody_account.account_number that the original transaction used. This means finance staff can trace every payout obligation back to the specific custody account that holds the funds.
Use split_payout to see outstanding payout obligations grouped by entity (TMT vs. Client) and currency. The amounts in those reports correspond directly to funds sitting in the referenced custody accounts.

Build docs developers (and LLMs) love