externalReferenceId and accountId of the user it belongs to. There is no per-user cap — page with nextCursor to walk every transaction in the window across every target user.
Defaults to the last 90 days when no date filter is supplied.
Breaking change. This query previously returned
results, one entry per target user, each holding up to 20 transactions. It now returns a flat transactions list with cursor pagination. See Migrating from the per-target response.Requirements
Authorization: Basic <API_KEY>(your application API key)- The bulk API capability on your application
- The
LIST_PAYMENTandLIST_PURCHASESscopes on each target user’s grant
Query
Variables
Response
Arguments
The date window bounds the data;
limit bounds a single page. The window may span at most 365 days. Transactions are stored in monthly partitions and each partition in the window is scanned per target, so a wider window costs more per page — it isn’t free. For longer history, use the export.
Targeting
targetSpec.mode is either SELECTED (name the users in targets, using the externalReferenceId you connected them with) or ALL_CONNECTED (every user with an active grant on your application). Duplicate targets are removed.
This query accepts up to 1,000 target users. For more than that, use the asynchronous export.
Response fields
BulkTransaction
Four behaviors to be aware of:
transactionTypeis a human-readable label, not a stable enum — values look like"Account Transfer - In"or"Add Money", notTRANSFERorDEPOSIT. The set is open and the wording may change. Don’t switch on it in code; userecordIdand the amount/sign for logic, and treat this field as display text.- Only
PENDINGandSETTLEDtransactions are returned — declined and other non-baseline records are excluded, matching the single-user transactions surface. - Ordering is newest first across the whole flat stream (
createdAtdescending, ties broken byrecordId, then by user). - A transaction on a shared account appears once per grant that can see it — two attributed rows with the same
recordIdand differentexternalReferenceId.
BulkTransaction is a purpose-built, narrow type. It is not the full Transaction type returned by the single-user transactions query — the fields above are the complete set. For richer per-transaction data, use the asynchronous export.
BulkTargetFailure
A failed target never fails the request.
Select both identifiers.
externalReferenceId is null for any grant you connected without one, so on its own it may not tell you which user failed. accountId is populated whenever the target resolved — which is the case for INSUFFICIENT_SCOPE and ACCOUNT_NOT_PERMITTED — and is null only for TARGET_NOT_CONNECTED and INVALID_TARGET_IDENTIFIER, where nothing resolved. Querying errors { externalReferenceId accountId code message } means every entry is identifiable by at least one of the two.
Request-level errors
Everything above is per-target. These reject the whole request, returningdata.getBulkTransactions: null plus a GraphQL error. Branch on extensions.code, never on the message text — wording can change, codes won’t.
The two date failures share a code — both mean “the range you asked for isn’t usable” — and the
message distinguishes them:
APPLICATIONS-0010 before it reaches the database. Treat it as “start again from page one”, not as retryable.
Paging
Read the first page, then follownextCursor until hasMore is false. Keep every other argument identical across pages — the cursor encodes a position in that specific query’s ordering.
Migrating from the per-target response
When to use the export instead
getBulkTransactions can walk complete history by paging, so the export is for pulls you’d rather not page through — more than 1,000 users, windows longer than a year, scheduled batch jobs, or when you need richer per-transaction fields than BulkTransaction carries. Submit GET_TRANSACTIONS_EXPORT via submitBulkOperation, poll getBulkOperationJob, and download the NDJSON from the short-lived resultUrl. See Bulk Operations.