Transactions

Bulk operations

Changed on

Execute multiple operations (create transactions, add metadata, revert transactions, delete metadata) in a single request. Requires ledger:write scope.

With atomic=true, all elements target the URL's ledger and are submitted as one batch. Idempotency-Key identifies that whole batch; per-element ik values are ignored. With atomic=false (default), each element is submitted separately under its own ik; the header is ignored.

continueOnFailure controls sequential continuation and business-error status rollup. It does not allow partial application of an atomic batch. Non-atomic failures can follow already committed elements: inspect every result and preserve the original identities when retrying. A timeout or infrastructure failure does not prove that work was not committed. This contract does not enable automatic SDK retries.

The response status is decided in three tiers:

  1. Request-level failures (before per-element processing): malformed body → 400, missing/insufficient scope → 401 or 403, too many elements → 413. Exceeding the byte limit while decoding the body currently returns 400. Returned unconditionally, continueOnFailure does not apply.
  2. Infrastructure failures during processing (transport timeout, cache-horizon exceeded, storage error): the overall status is 503 for retryable failures and 500 otherwise, regardless of continueOnFailure. Callers must inspect the element outcomes before deciding what to retry.
  3. Per-element errors during processing: each element's error carries the HTTP status it would surface as a single request (via the same mapping handleError uses). The top-level status is the "worst" of them, with continueOnFailure applying only to per-element business failures (4xx):
    • Business failures (validation, not-found, conflict, precondition, permission — 4xx): rolled up per continueOnFailure. true → 200; false (default) → the highest 4xx among failing elements (typically 400).
    • Resource exhaustion (KindResourceExhausted, 429), including rate limits and permanent authoritative-sequence exhaustion: surface unconditionally as 429.
    • Retryable infrastructure failures (leader loss, cache-horizon exceeded, KindUnavailable): surface as 503 with Retry-After: 1, regardless of continueOnFailure.
    • Non-retryable infrastructure failures (transport / storage errors, KindInternal, unclassified): surface as 500.
    • Aborted elements (context.Canceled from the sequential runner after a prior failure): contribute nothing — the originating error drives the rollup.
post/v3/{ledgerName}/bulk

Request

  • Base URL
    http://localhost:9000
  • URL
    http://localhost:9000/v3/{ledgerName}/bulk
  • Auth
    • HTTP bearer
    • or none

Path parameters

ledgerNamestring required

Name of the ledger

Query parameters

continueOnFailureboolean

Continue sequential processing after a failure and suppress the top-level status for business errors. Does not suppress 429 or 5xx failures, or permit partial application when atomic=true.

atomicboolean

Submit all operations as one atomic batch under the optional Idempotency-Key header. Per-element ik values are ignored. All elements target ledgerName. On failure every element reports the batch error; continueOnFailure does not change atomicity.

Headers

Formance-Bigint-As-Stringstring

Render all response Uint256, BigUint and SignedBigInt values as canonical decimal strings, regardless of business meaning, including posting amounts, volume input/output and balances. Ordinary integer IDs/counts, metadata and explicitly string-encoded counters keep their existing representation. Case-insensitive true, yes, y and 1 enable this option, matching Ledger v2. Whitespace is not trimmed. Omission and every other value retain JSON number tokens. This affects only this response, including nested objects, maps, arrays, transaction/log/cursor and bulk results. Request decoding is unchanged.

Idempotency-Keystring

Idempotency key for the request

Request body

action'CREATE_TRANSACTION' | 'ADD_METADATA' | 'REVERT_TRANSACTION' | 'DELETE_METADATA' required

The type of operation to perform. The REST bulk endpoint accepts these four actions only; account-type actions (ADD_ACCOUNT_TYPE / REMOVE_ACCOUNT_TYPE) are gRPC-only and are rejected here.

ikstring

Idempotency key for this operation

skippableReasonsstring[]

Opt-in continue-on-failure list for this entry. When the FSM would otherwise reject the underlying order with a business error whose typed reason matches one of these entries, the order is recorded as an OrderSkippedLog (no state mutation) and the bulk result's data surfaces the skip context. Reasons outside the per-action business whitelist (structural / internal reasons) are rejected at admission. Accepted reasons per action on this REST endpoint:

  • CREATE_TRANSACTION → TRANSACTION_REFERENCE_CONFLICT
  • REVERT_TRANSACTION → TRANSACTION_ALREADY_REVERTED
  • DELETE_METADATA → METADATA_NOT_FOUND The FSM also supports skipping ADD_ACCOUNT_TYPE (ACCOUNT_TYPE_ALREADY_EXISTS) and REMOVE_ACCOUNT_TYPE (ACCOUNT_TYPE_NOT_FOUND), but those actions are gRPC-only: the REST bulk endpoint does not accept account-type actions (see the action enum above), so their reasons are not offered here. Empty (default) preserves the historical fail-on-error behaviour.

Response

Bulk operations completed

errorCodestring
errorMessagestring

Changes

    • info

      api operation id bulkOperations removed and replaced with v3BulkOperations

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////////// from the response with the status

    • warning

      removed the optional property /////// from the response with the status

    • warning

      removed the optional property /////// from the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////////// to the response with the status

    • info

      added the required property /////// to the response with the status

    • info

      added the required property /////// to the response with the status