Skip to main content
A cash pool is a collection of payment accounts from one or more payment service providers that you want to manage as a single unit. Cash pools aggregate balances across multiple accounts, providing a unified view of your funds for financial reporting, treasury management, and reconciliation. Cash pools can be created in two ways:
  • Static pools: Explicitly specify which accounts to include
  • Dynamic pools: Define criteria that automatically match accounts

Why cash pools?

When managing funds across multiple financial institutions, you often need to view and analyze balances from different accounts together. For example, you might have:
  • A Stripe account for card payments
  • A PayPal account for alternative payments
  • A bank account for direct transfers
Rather than querying each account individually, cash pools let you:
  • View aggregated balances across all accounts in real-time
  • Track historical balances at specific points in time
  • Simplify financial reporting with consolidated balance views
  • Enable reconciliation against your internal ledger
  • Monitor liquidity across multiple financial institutions
  • Automatically include new accounts that match your criteria (dynamic pools)

Pool structure

A cash pool contains:
  • ID: Unique UUID identifier
  • Name: Human-readable name (must be unique)
  • Created at: Timestamp when the pool was created
  • Pool accounts: Array of account IDs included in the pool (for static pools)
  • Query: JSON query defining account matching criteria (for dynamic pools)

Creating cash pools

Cash pools are created via the Payments API using one of two approaches:

Static pools

Specify exact accounts to include in the pool:
{
  "name": "My Static Pool",
  "accountIDs": [
    "stripe:acc_1234567890",
    "wise:account-uuid-here"
  ]
}

Dynamic pools

Define criteria that automatically match accounts:
{
  "name": "All USD Stripe Accounts", 
  "query": "{\"$match\": {\"connector_id\": \"stripe:connector-id\", \"default_asset\": \"USD\"}}"
}
Static pools require explicit account IDs, while dynamic pools use JSON query syntax. The two approaches are mutually exclusive - you cannot specify both accountIDs and query in the same request.

Query syntax

Dynamic pools use the same query syntax as the List Accounts API. Supported query fields include:
  • connector_id: Match accounts from specific connectors
  • default_asset: Filter by currency/asset
  • type: Account type (e.g., INTERNAL, EXTERNAL)
  • name: Account name matching
  • psu_id: Payment service user ID
  • metadata.: Custom metadata fields

Query examples

All EUR accounts across connectors:
{
  "name": "EUR Accounts",
  "query": "{\"$match\": {\"default_asset\": \"EUR\"}}"
}
Stripe accounts only:
{
  "name": "Stripe Pool",
  "query": "{\"$match\": {\"connector_id\": \"stripe:connector-123\"}}"
}
Internal accounts with specific metadata:
{
  "name": "Business Accounts",
  "query": "{\"$match\": {\"type\": \"INTERNAL\", \"metadata.category\": \"business\"}}"
}

Static vs. Dynamic pools

FeatureStatic PoolsDynamic Pools
Account membershipStatic - explicitly definedDynamic - automatically updated
New accountsMust be manually addedAutomatically included if they match criteria
Use caseKnown, fixed set of accountsAccounts that change frequently or match patterns
ManagementRequires manual updatesSelf-maintaining
Account operationsCan add/remove individual accountsCannot modify - accounts determined by query

When to use static pools

  • Fixed account sets: When you have a specific, unchanging group of accounts
  • Mixed criteria: When accounts don’t follow a consistent pattern
  • Fine-grained control: When you need to include/exclude specific accounts manually

When to use dynamic pools

  • Dynamic environments: When new accounts are frequently created
  • Connector-based grouping: All accounts from a specific payment provider
  • Currency segregation: Separate pools for different currencies
  • Automated workflows: When pools need to be configured declaratively via API
Dynamic pools do not support manual account addition or removal. To modify membership, update the pool’s query criteria.

Using cash pools

Balance queries

Pool balance endpoints aggregate balances from all accounts in the pool by asset:
# Get latest aggregated balances
GET /pools/{poolId}/balances/latest

# Get historical balances at specific timestamp (must be in past)
GET /pools/{poolId}/balances?at=2024-01-15T23:59:59Z
Balance aggregation logic:
  1. Static pools: Fetches balances from the specified account IDs
  2. Dynamic pools: Runs the query to find matching accounts, then fetches their balances
  3. Groups by asset/currency
  4. Sums amounts for each asset
  5. Returns array of aggregated balances
Dynamic pools resolve their account membership dynamically at query time, ensuring balances always reflect the current set of accounts matching your criteria.

Reconciliation policies

Cash pool IDs are used in the paymentsPoolID field of reconciliation policies:
{
  "name": "string",
  "ledgerName": "string", 
  "ledgerQuery": "object",
  "paymentsPoolID": "uuid-string"
}
The reconciliation service compares ledger account balances against the aggregated cash pool balances. See Getting Started with Reconciliation for a complete workflow.