Simulation Scenarios

Transaction kinds and the events that move them through their lifecycle.

Every simulated transaction starts with one creation call and, optionally, moves through its lifecycle via POST /transaction/update. Which creation call you use depends on what you’re simulating.

Creating a transaction

Each simulated transaction kind has its own creation endpoint:

EndpointSimulates
POST /transaction/cardA card purchase, funded from the card’s Capital Account.
POST /transaction/paymentA payment between a linked account and a Capital Account, in either direction.

Neither endpoint simulates card refunds or transfers between two of your own Capital Accounts. POST /transaction/card produces an outbound purchase only, and POST /transaction/payment exchanges with a linked account only. Use POST /accounts/capital/transfer on Penny Banking for transfers.

Card purchases

POST /transaction/card takes these fields:

FieldRequiredDescription
card_idYesThe card making the purchase.
amountYesDecimal string in major units, greater than zero, such as "25.00" for $25.00.
currencyYesUSD.
merchantYesWhere the purchase is made. See the merchant fields below.
acquirerYesThe acquiring bank submitting the purchase: id (required) and name (optional).
forceNoDefaults to false. See below.

The merchant object:

FieldRequiredDescription
nameYesThe merchant’s display name.
category_codeYesThe four-digit merchant category code (MCC) as a string, such as "5411" for grocery stores. Merchant rules match on this value.
merchant_idNoThe network’s identifier for the merchant. Reuse the same value to simulate repeat purchases at one merchant. When omitted, Penny derives a stable identifier from the merchant’s name and location.
cityNoThe merchant’s city.
zip_codeNoThe merchant’s postal or ZIP code.
countryNoISO 3166-1 alpha-2 country code, such as US. Geographic rules match on this value.
subdivisionNoISO 3166-2 code of the merchant’s state or province, such as US-NY. Must belong to country when both are sent.

The force flag controls authorization:

  • force: false (default) — runs the purchase through Penny’s authorization: account and card eligibility, available funds, spend controls, and any configured live decisioning callback. Penny records its decision (transaction.request.approved or transaction.request.declined), and the simulator then confirms it the way a card network would (transaction.approved or transaction.declined). You do not trigger that confirmation step. A decline is still a successful simulation response that contains a declined transaction.
  • force: true — bypasses authorization and records the transaction as settled (transaction.settled), modeling an offline or store-and-forward capture that arrives with no prior authorization.

See Simulating a Card Purchase for a worked example.

Linked account payments

POST /transaction/payment takes linked_account_id, capital_account_id, amount, and currency (USD), all required, plus:

  • direction (default inbound) — inbound for a payment received from the linked account, outbound for a payment sent to it.
  • settle (default false) — true settles the payment immediately; false leaves it approved until you send a transaction.settled event with POST /transaction/update.

Transaction events

Once a transaction exists, POST /transaction/update advances it with one of four events:

EventUse
transaction.settledPartial, repeated, or full settlement. amount required and positive.
transaction.adjustmentA signed change to the pending amount — negative for a reduction. amount required and non-zero.
transaction.cancelledReleases the pending hold. amount optional — omit it to release the full pending amount.
transaction.expiredExpires the authorization under Penny’s lifecycle rules. amount optional — omit it to release the full pending amount.

An optional reason string is recorded on the event for any of these.

Only the four events above are accepted by POST /transaction/update. The request and approval events happen automatically when a card transaction is created (see above), and any other event value is rejected with 400.

Settlement and adjustment amounts are deltas, not cumulative totals. Send a second settlement event with its own amount to exercise multi-part settlement. To model a reversal, send a negative transaction.adjustment, or a separate payment in the opposite direction.

Penny validates each event against the transaction’s current state, as it does for real activity. An event that is not valid from the transaction’s current state is rejected with 422.

Reading a simulated transaction back

Read a simulated transaction through Penny Banking’s GET /transactions/{transaction_id} endpoint, or through a transaction list scoped to its card or account. See Transactions.

Idempotency

POST /transaction/card, POST /transaction/payment, and POST /transaction/update accept an Idempotency-Key header. It is optional, but strongly advised. Use a new key for each intended event, and reuse the same key, with the same body, only when retrying that exact event. A request still being processed under the same key returns 409. See Retries & Idempotency.