ROOKDocs
Transactions Guide

Moving money

Every financial event in Rook is a transaction, and every movement of funds happens inside one: there is no transfer without a transaction. A transaction holds one or more immutable transfers (the movements of funds), and each transfer posts one book transfer of balanced book entries.

Card authorizations, captures, and refunds are transactions of type CARD; Rook creates their transfers from network events. This guide covers the transaction types you create to move money, and the ones Rook posts for fees, interest, disputes, and rewards.

Transaction types you create

All four are created through their own endpoint and returned as a Transaction (object transaction, type set). The id is the transaction_id used on GET /v1/transactions/{transaction_id}, …/transfers, and …/book-transfers. They share the movement fields (status, amount, wallet_id, financial_account_id, direction, category, memo, events[], transfer_ids[]) and the same Money shape: integer minor units plus an ISO 4217 currency. direction is CREDIT or DEBIT relative to financial_account_id; amount is always non-negative.

typeUse whenPath
INTERNAL_TRANSFERBoth legs are financial accounts on this program/v1/internal-transfers
PAYMENTYou originate a payin or payout to an external bank account (ACH, RTP, FedNow)/v1/payments
EXTERNAL_PAYMENTThe rail ran off-platform (wire, ACH, check, or transfer) and the books need a matching transaction/v1/external-payments
MANAGEMENT_OPERATIONAn operator posts a fee, dispute outcome, reward, adjustment, or disbursement on one financial account (single-leg)/v1/management-operations
GET /v1/transactions?type=… lists the same objects. Pick the type that matches how the funds actually move: do not record an originated ACH as an external payment, and do not use a management operation to move money between two financial accounts.

Transaction types Rook posts for you — FEE, INTEREST, DISPUTE, REWARD — appear on GET /v1/transactions and in the activity feed with the same shape.

Program caps for ACH, wire, RTP, FedNow, and internal transfers live on Transfer limits.

Every creating or lifecycle POST requires Idempotency-Key. Replay of the same method, path, and body within 24 hours returns the original status and payload.

Shared object

status is the transaction status (one set for every type). events[] is the transaction's lifecycle log, chronological; transfers themselves never change. Discriminate each item on type:

typeMeaning
CREATEDThe request was accepted.
SETTLEDThe amount posted to the ledger.
DECLINEDThe amount never posted.
RETURNEDAn ACH return unwound a settlement.
REVERSEDAn API reverse unwound a settlement.
RELEASEDA pending external-payment hold was dropped without posting.
CANCELEDA pending external payment was voided.
Each event has amount (integer minor units), result (APPROVED or DECLINED), financial_account_id, and created_at.

Internal transfers

Move funds between two financial accounts on the program. The source (from_financial_account_id) is debited; the destination (to_financial_account_id) is credited. On the object, financial_account_id equals the source and direction is DEBIT.

category selects the reason; subtype is the subtype. Valid pairs:

categorysubtype
TRANSFERCOLLECTION, PAYMENT
ADJUSTMENTBILLING_ERROR, BILLING_ERROR_REVERSAL, CORRECTION, GOODWILL
BALANCE_OR_FUNDINGAVAILABLE_TO_RESERVE, RESERVE_TO_AVAILABLE, AVAILABLE_TO_SUSPENSE, SUSPENSE_TO_AVAILABLE
FEELATE, NSF, ANNUAL, ATM, FOREIGN_TRANSACTION, FEE_REVERSAL
REWARDCASH_BACK, CASH_BACK_REVERSAL, PROMO, PROMO_REVERSAL
PROGRAM_FUNDINGPROGRAM_FUNDING, PROGRAM_REPAYMENT
A mismatched pair returns 400 invalid_request with param: subtype. Use TRANSFER / COLLECTION to pull from a cardholder issuing financial account onto the program operating account. Use BALANCE_OR_FUNDING to reclassify available, reserve, and suspense on the same program.

Status subset: PENDING, SETTLED, DECLINED, REVERSED.

mermaid
stateDiagram-v2
  [] --> SETTLED: create approved
  [] --> DECLINED: create declined
  DECLINED --> SETTLED: retry approved
  DECLINED --> DECLINED: retry declined
  SETTLED --> REVERSED: reverse
Code
  create approved ──► SETTLED ── reverse ──► REVERSED

create declined ──► DECLINED ─┬─ retry approved ──► SETTLED └─ retry declined ─► DECLINED

  • Create: POST /v1/internal-transfers
  • Reverse: POST /v1/internal-transfers/{internal_transfer_id}/reverse on SETTLED
  • Retry: POST /v1/internal-transfers/{internal_transfer_id}/retry on DECLINED
List financial_account_id matches source or destination.

Linking bank accounts

A Payment needs a linked external bank account whose state is ENABLED and whose verification_state is ENABLED. Link the bank before you originate ACH. Reads return last_four and the ABA routing_number. The full account number is never returned.

Create with POST /v1/external-bank-accounts. Send either bank details or a processor token, not both. account_number and processor_token are write-only.

BodyRequired fieldsTypical verification_method
Bank detailsrouting_number, account_number, type (CHECKING or SAVINGS), owner, owner_type (PERSON or BUSINESS)MANUAL, MICRO_DEPOSIT, or PRENOTE
Processor tokenprocessor_token, owner, owner_typeEXTERNALLY_VERIFIED
MICRO_DEPOSIT and PRENOTE also need address plus date_of_birth (person) or tax_id (business). tax_id and date_of_birth are write-only.

state is the origination lifecycle. verification_state is ownership proof. Both must be ENABLED to originate.

stateMeaning
ENABLEDMay originate when verification also passed.
PAUSEDOrigination declined until unpause.
CLOSEDTerminal. No origination.
verification_stateMeaning
PENDINGOwnership proof running (micro-deposits or prenote).
ENABLEDPassed.
FAILED_VERIFICATIONRejected. Retry or change method.
INSUFFICIENT_FUNDSA micro-deposit could not post. Retry after the bank can accept a credit.
mermaid
stateDiagram-v2
  [] --> PENDING: MICRO_DEPOSIT or PRENOTE create
  [] --> ENABLED: MANUAL or EXTERNALLY_VERIFIED create
  PENDING --> ENABLED: amounts match / prenote succeeds
  PENDING --> FAILED_VERIFICATION: mismatch or prenote return
  PENDING --> INSUFFICIENT_FUNDS: micro-deposit cannot post
  FAILED_VERIFICATION --> PENDING: retry or set method
  INSUFFICIENT_FUNDS --> PENDING: retry
Code
  create MANUAL / EXTERNALLY_VERIFIED ──► verification_state ENABLED

create MICRO_DEPOSIT / PRENOTE ──► PENDING ─┬─ success ──► ENABLED ├─ mismatch ─► FAILED_VERIFICATION ── retry ──► PENDING └─ NSF ──────► INSUFFICIENT_FUNDS ── retry ──► PENDING

  • Verify micro-deposits: POST .../micro-deposits with the two
credit amounts (Money: integer cents plus USD). Both must match.
  • Retry micro-deposits: POST .../micro-deposits/retry posts a
new pair.
  • Retry prenote: POST .../prenote/retry sends a new zero-dollar
ACH prenotification.
  • Set method: POST .../verification-method to switch onto
MICRO_DEPOSIT or PRENOTE, or to pick a new method after failure.
  • Pause / unpause: POST .../pause and POST .../unpause toggle
state between ENABLED and PAUSED. They do not change verification.

PATCH /v1/external-bank-accounts/{external_bank_account_id} updates nickname, owner, address, and user_defined_id only. List filters: wallet_id, owner_type, state, verification_state.

Subscribe to external_bank_account.updated for state and verification changes.

Payments

Originate an ACH payin or payout against an external bank account that is ENABLED with verification_state ENABLED. PAYIN credits financial_account_id (pull from the bank). PAYOUT debits it (push to the bank). method is ACH_NEXT_DAY, ACH_SAME_DAY, RTP, or FEDNOW. sec_code is CCD (corporate), PPD (consumer), or WEB (internet-initiated). category is ACH, RTP, or FEDNOW, derived from method; sec_code is null on instant rails.

Status: PENDING, SETTLED, DECLINED, RETURNED, REVERSED. return_reason_code is a NACHA code (R01 insufficient funds, R02 wallet closed, and the rest of the closed set) when status is RETURNED, and null otherwise.

mermaid
stateDiagram-v2
  [] --> PENDING: create accepted
  [] --> DECLINED: create declined
  PENDING --> SETTLED: ACH settles
  DECLINED --> PENDING: retry
  SETTLED --> RETURNED: return
  SETTLED --> REVERSED: network reverse
Code
                    ┌─────────────────────────────────┐
  create accepted ─►│            PENDING              │
                    └──────────────┬──────────────────┘
                                   │ ACH settles
                                   v
                                SETTLED ─┬─ return ──────────► RETURNED
                                         └─ network reverse ─► REVERSED

create declined ──► DECLINED ── retry ──► PENDING

  • Create: POST /v1/payments
  • Retry: POST /v1/payments/{payment_id}/retry on DECLINED
  • Return: POST /v1/payments/{payment_id}/return on SETTLED with return_reason_code
Use this family only when Rook originates the ACH. A wire or ACH that already happened at the bank is an external payment.

External payments

Record a movement that originated outside Rook so balances stay correct. category is EXTERNAL_WIRE, EXTERNAL_ACH, EXTERNAL_CHECK, or EXTERNAL_TRANSFER. Set direction relative to financial_account_id. effective_date is the business date (YYYY-MM-DD).

On create, omit progress_to to leave the object PENDING. Pass SETTLED or RELEASED to skip the hold.

Status: PENDING, SETTLED, RELEASED, CANCELED, REVERSED.

mermaid
stateDiagram-v2
  [] --> PENDING: create
  [] --> SETTLED: create progress_to SETTLED
  [] --> RELEASED: create progress_to RELEASED
  PENDING --> SETTLED: settle
  PENDING --> RELEASED: release
  PENDING --> CANCELED: cancel
  SETTLED --> REVERSED: reverse
Code
                    ┌─────────────────────────────────┐
  create ──────────►│            PENDING              │
                    └───┬──────────┬──────────┬───────┘
                        │          │          │
                   settle     release      cancel
                        │          │          │
                        v          v          v
                     SETTLED    RELEASED   CANCELED
                        │
                     reverse
                        v
                     REVERSED

create progress_to SETTLED ──► SETTLED create progress_to RELEASED ──► RELEASED

  • Settle: POST .../settle posts pending funds (amount may be a partial)
  • Release: POST .../release drops the hold without posting
  • Cancel: POST .../cancel voids a pending record
  • Reverse: POST .../reverse undoes a settlement
Settle when the off-platform movement landed. Release when it will not land and the hold should drop. Cancel when the record was created in error. Reverse when a settled record must be unwound.

Management operations

Post an operator adjustment on a single financial account. Set direction relative to that financial account. category and subtype must match:

categorysubtype
MANAGEMENT_FEELATE, NSF, ANNUAL, ATM, FOREIGN_TRANSACTION, OTHER
MANAGEMENT_DISPUTECHARGEBACK, REPRESENTMENT, WON, LOST
MANAGEMENT_REWARDCASH_BACK, PROMO, POINTS_REDEMPTION
MANAGEMENT_ADJUSTMENTGOODWILL, CORRECTION, CHARGE_OFF, WRITE_OFF
MANAGEMENT_DISBURSEMENTDISBURSEMENT
Status subset: PENDING, SETTLED, DECLINED, REVERSED.
mermaid
stateDiagram-v2
  [] --> SETTLED: create approved
  [*] --> DECLINED: create declined
  SETTLED --> REVERSED: reverse
Code
  create approved ──► SETTLED ── reverse ──► REVERSED
  create declined ──► DECLINED
  • Create: POST /v1/management-operations
  • Reverse: POST /v1/management-operations/{management_operation_id}/reverse on SETTLED
Use an internal transfer when two financial accounts exchange funds. Use a management operation when one financial account should move without a book counterparty (for example a late fee or goodwill credit).

Books

Every settled transaction posts one book transfer per transfer it holds, to the books of the financial accounts involved. A book transfer is the collection of balanced book entries (debits and credits) one transfer posts; book entries are never presented on their own. Read a transaction's transfers with GET /v1/transactions/{transaction_id}/transfers, its book transfers with GET /v1/transactions/{transaction_id}/book-transfers, the books of a financial account with GET /v1/financial-accounts/{financial_account_id}/books, and the book transfers posted to them with GET /v1/financial-accounts/{financial_account_id}/book-transfers?transaction_id=….

Activity feed

Every transaction that touches a financial account appears once on GET /v1/financial-accounts/{financial_account_id}/activity, with transaction_id and a category that mirrors the transaction type: CARD, INTERNAL_TRANSFER, PAYMENT, FEE, INTEREST, DISPUTE, and ADJUSTMENT for management operations. The feed is a view; the transaction is the source of truth.