Subtransactions¶
A Subtransaction is the per-end-user record of the true parties behind a Transaction. It exists to de-nest bulk transactions that bundle many sender-to-beneficiary flows into a single rail-level event (an ACH credit, an outbound wire, a book transfer, and so on). The full Subtransactions API surface covers creation, linking, search, and lifecycle of these records.
Subtransactions are not themselves payments. They do not initiate ACH, wire, ICL, or BOOK transfers on any rail. They are records of who the underlying parties actually are, linked to the parent Transaction that DID move money on a rail.
If your program handles cross-border remittance, payroll, marketplace payouts, or any other flow where one rail-level transaction represents many end-user payments, you almost certainly need Subtransactions. Without them, the per-end-user parties are invisible to GIB's monitoring and screening.
When you need subtransactions¶
The most common case is cross-border remittance:
- The senders are individual US end users.
- Their funds are bundled into a single bulk transaction (typically an outbound ACH credit or international wire) sent to a liquidity provider, international affiliate, or payment service provider.
- That recipient takes the bulk and pays out the many true beneficiaries in the destination country and currency.
The bulk Transaction is the only thing that hits GIB's rails. By itself, it tells you only that "your fintech sent $X to a liquidity provider." It tells you nothing about the true senders (the US end users) or the ultimate beneficiaries (the foreign recipients). Subtransactions are how that "true parties" record reaches GIB.
The same de-nesting pattern applies to any flow where one rail-level Transaction represents many underlying end-user payments. Cross-border remittance is the most prominent example, but B2B mass payouts, marketplace settlements, payroll bulk credits, and treasury sweeps are common candidates as well. If your program bundles end-user payments into a single rail event for any reason, Subtransactions are how you keep the per-end-user record visible to compliance.
Why this matters for compliance¶
Bundling without de-nesting is a nested correspondent flow. Three reasons that's hard to defend:
- BSA / AML. GIB's transaction monitoring needs to evaluate the per-end-user records, not just the bulk. Subtransactions are how that data reaches monitoring.
- OFAC. GIB screens the counterparty on the bulk Transaction (the liquidity provider). Subtransactions give GIB the true senders and beneficiaries to screen against as well. A sanctions hit on a true beneficiary would otherwise be invisible.
- Travel Rule. The originator-and-beneficiary information requirements of the Travel Rule attach to the per-payment relationship between the true parties, not to the bulk. Subtransactions are the per-payment record.
In short: GIB screens the bulk Transaction; Subtransactions tell GIB who else to screen against, and they are how monitoring and Travel Rule obligations stay defensible at scale.
How they relate to Subclients¶
A Subtransaction references two Subclients: an origin (the true sender) and a destination (the true beneficiary, or in some patterns an intermediary). Each Subclient has a relationship_type field that classifies its role:
relationship_type |
Typical role in a Subtransaction |
|---|---|
customer |
An end user of your program, typically the true sender |
beneficiary |
The true recipient of the underlying payment |
payment_service_provider |
A PSP / liquidity provider in the intermediating path |
affiliate |
An international affiliate of your company performing the payout |
root |
The root entity (your Company itself), rarely the right type here |
counterparty |
A generic counterparty role for less-common patterns |
The non-customer relationship types exist precisely to support this de-nesting. Set them correctly when you create Subclients; they aren't just labels, they are how the compliance picture comes together when monitoring reads the Subtransaction.
Linking to Transactions¶
Subtransactions are linked to their parent Transactions, not nested inside them. The relationship is many-to-many:
- One bulk Transaction (the rail-level ACH credit, wire, or book transfer) can link to many Subtransactions.
- A single Subtransaction can be linked to one or more parent Transactions. This matters when an end user's underlying flow traverses multiple rail legs, for example a BOOK transfer from a virtual account to your operations account followed by an outbound ACH or wire from operations to the liquidity provider. One Subtransaction represents the end-user flow; both parent Transactions are linked to it.
The link is created and managed through dedicated link endpoints (see How to create them below).
Fields¶
From code/api/shared_types/subtransaction.yaml:
| Field | Purpose |
|---|---|
id |
GIB identifier |
external_key |
Your platform's identifier for this Subtransaction (see Idempotency) |
subclient_origin_id |
The Subclient ID of the true sender |
subclient_destination_id |
The Subclient ID of the true recipient (or intermediary) |
amount |
Amount in cents for this specific end user's portion |
currency |
ISO 4217 currency code (e.g. USD). This is the field you set on creation. See the Currencies reference for all supported codes, symbols, and decimal places. |
currency_id |
GIB's internal currency identifier, resolved from currency; read-only. Returned on responses only. |
fees |
Fees charged by the bank client for this specific end user's portion, in cents |
purpose |
The purpose of the payment (e.g. "Remittance"); used for compliance routing and beneficiary-side disclosure |
transfer_direction |
outbound (typical) or inbound; informational on the Subtransaction itself since it is not a rail event |
reference |
A free-text reference for the underlying payment |
date_time |
The date and time of the underlying payment (UTC, zero-offset / Zulu) |
subclient_origin_name / subclient_destination_name |
Resolved names; read-only |
company_id / company_name |
The Company; read-only |
create_* / update_* |
Audit metadata; read-only |
deleted |
Soft-deletion flag |
Required on creation: subclient_origin_id, subclient_destination_id, amount, currency, transfer_direction, date_time.
How to create them¶
There are three paths, picked by how the Subtransaction relates to its parent Transaction(s).
Path 1: standalone Subtransaction creation. Call createSubtransaction (POST /subtransaction) with the full Subtransaction body (origin/destination Subclient IDs, amount, currency, direction, date_time, plus optional external_key, purpose, reference, fees). This creates the Subtransaction independently of any parent Transaction. Use this when you'll be linking the same Subtransaction to multiple parent Transactions later, the multi-leg pattern under Linking to Transactions.
Path 2: auto-creation when you create the parent Transaction. On POST /transaction/from-subledger (createTransaction), include true_sender_subclient_id and/or ultimate_beneficiary_subclient_id in the request body. The API creates a Subtransaction and links it to the new parent Transaction in the same call. The Subtransaction's subclient_origin_id is taken from true_sender_subclient_id (or from the parent's origin_subclient_id if not supplied), and subclient_destination_id from ultimate_beneficiary_subclient_id (or from the parent's destination_subclient_id).
Note:
createTransactionis currently BETA and supports onlyachandbookrail types. For wire, wire20022, or ICL parent Transactions, use Path 1 (standalone create) + Path 3 (link) instead.
POST /transaction/from-subledger
{
"type": "book",
"origin_subclient_id": "<sender Subclient ID>",
"destination_subclient_account_id": "<operations account ID>",
"true_sender_subclient_id": "<true sender Subclient ID>",
"ultimate_beneficiary_subclient_id": "<true recipient Subclient ID>",
"external_key": "PIF-TX-007",
"purpose": "Remittance",
"reference": "INV-2025-Q1-003",
"amount": 10000,
"fees": 250
}
Path 3: link an existing Subtransaction to a parent Transaction. Call createTransactionSubtransactionLink (POST /transaction/{transaction_id}/subtransaction) with body { "subtransaction_id": <id> }. The endpoint takes an existing Subtransaction by ID and links it to the parent Transaction identified in the URL path. Call this once per parent Transaction you want to link the Subtransaction to.
Search across all Subtransactions globally via getSubtransactions, or list Subtransactions linked to a specific parent Transaction via getTransactionSubtransactions.
For the end-to-end walkthrough with Subclient setup, parent Transaction creation, and the subsequent sweep to the liquidity provider, see Tracking Remittance Through Sweep to Third Party.
Lifecycle¶
Subtransactions do not have their own rail-level lifecycle. They exist as records and follow the parent Transaction(s) they are linked to. A Subtransaction is "live" as long as at least one parent Transaction it's linked to is live. Soft-deletion (deleted=true) is the way to take a Subtransaction out of the active set without erasing the audit history.
Webhook events¶
State transitions occur on parent Transactions, not on Subtransactions directly. When you receive a webhook on a parent Transaction, retrieve its linked Subtransactions via getTransactionSubtransactions. See Webhooks for the event-type catalog and delivery semantics.
Related concepts¶
- Transactions, the parent record that actually moves money on a rail
- Subclients, and the
relationship_typeenum that classifies the parties - Subclient Accounts, the accounts a Subclient may hold
- Idempotency,
external_keyapplies to Subtransaction creation the same way it applies to Transactions - Tracking Remittance Through Sweep to Third Party, the canonical end-to-end walkthrough