Skip to main content
Applies to Program-Funded programs. See Overview for the bigger picture.
A virtual asset posting is how you update an account’s virtual asset balances. Every posting carries a type that says what kind of change you mean, plus one or more entries listing the virtual assets and amounts involved. The whole posting is applied atomically: either all entries land, or none do.

The three types

typeWhat it doesTypical use
DEPOSITCredits the entries to the account’s virtual balance.User deposits with you, sign-up bonus, cashback, salary, top-up.
WITHDRAWALDebits the entries from the account’s virtual balance. Rejected if any entry would take a balance below zero.User withdraws from you, expiring a bonus, revoking unspent allowance.
SETTLEMENTDebits the entries from the account’s virtual balance and applies their USD value to outstanding card debt.Closing the loop after card spend.
All three go through the same call:
POST /postings
See POST /postings for the full request and response contract, including settledAmount and per-entry rateSnapshot returned for SETTLEMENT.
Submit multiple entries in one posting to apply correlated changes together. A multi-asset deposit, a multi-asset settlement, or a deposit-and-bonus stack all go in a single call, so partial states never become visible.

Patterns

Most programs fall into one of two shapes. They use the same endpoint and the same operations; what differs is what the balance represents on your side, and which postings you actually need.

Custodial mirror

You hold the user’s funds on your side - a custody wallet, an exchange account, a fund — and the virtual balance on Reap mirrors yours so the user can spend on their card.
  • User deposits with youDEPOSIT for the matching asset.
  • User withdraws from youWITHDRAWAL for the same asset.
  • User’s card spend has clearedSETTLEMENT for the asset they are paying with. Debits their virtual balance and clears the matching card debt in one step.
The third operation is what makes SETTLEMENT distinct from WITHDRAWAL. After a card swipe clears, you need to pull from the user’s holdings on your side to cover their card spend. A plain WITHDRAWAL for that pull would drop the user’s available balance a second time — once when the card debt accrued, again when the withdrawal posted. SETTLEMENT nets the two against each other so the user’s spending position only moves once and matches what they swiped. Each entry’s amount is the delta to apply, not the new total. A user depositing 100 USDC becomes a DEPOSIT with entries: [{ virtualAssetId: <USDC>, amount: "100" }]; a later 30 USDC withdrawal becomes a WITHDRAWAL with amount: "30".

Issued credits

You give the user balance — cashback, sign-up bonus, salary allowance — funded by your program rather than the user’s own holdings. Define one virtual asset per credit type (e.g., BONUS_USD with a FIXED rate of 1.00) and:
  • GrantDEPOSIT. The user can spend it on their next card swipe.
  • Revoke unused balanceWITHDRAWAL.
Whether you also need SETTLEMENT against the granted asset depends on how you want card debt to behave on the account; see the next section.

Settling card debt

SETTLEMENT is how you close card debt against a user’s virtual balance. You debit the user’s balance for the assets they are paying with, and Reap converts those amounts to USD and applies them against the account’s outstanding card debt in the same atomic step.
{
  "type": "SETTLEMENT",
  "entries": [
    { "virtualAssetId": "<USDC>", "amount": "12.50" }
  ]
}
You only pass virtual asset units. Reap computes the settled USD value using each asset’s rate at posting time, returns it as settledAmount on the response.

When you need it

For custodial mirror programs, SETTLEMENT is essential. It is how you pull from the user’s holdings to cover their card spend without dropping the user’s available balance twice. For issued-credit programs, SETTLEMENT is optional. The available balance equation assets - liabilities already shows the right number for the user — card debt subtracts from it as soon as a swipe clears, regardless of whether you post anything. Whether you also post SETTLEMENT against the credit depends on how you want the books to read:
  • Post SETTLEMENT to drain the credit’s virtual balance as the user spends. The virtual balance then reflects credit-still-available, and cardDebt.cleared returns to zero. Cleaner per-asset reporting; more API calls.
  • Skip SETTLEMENT and let cardDebt.cleared grow as the running total of granted-and-spent. The virtual balance reflects credit-ever-granted, and the user’s available position is still correct. Fewer calls; the per-asset view shows totals rather than remaining.
Pick what matches how you reconcile on your side. Both are valid.

How card debt is drained

Card debt on an account is split into two buckets:
  • pending — authorizations that have been approved but not yet cleared by the network.
  • cleared — cleared transactions awaiting settlement from you.
Each SETTLEMENT drains cleared first, then any overflow drains pending. You can read the current split from GET /accounts/:id/balance under liabilities.cardDebt.

Card debt can go negative

If you settle more than the user owes (or the user gets a refund after settlement), liabilities.cardDebt.total goes negative. Negative card debt is real credit on the account: it absorbs future card spend before any virtual balance is drained. Reap surfaces the structured split (pending, cleared, total) on the balance endpoint so you can decide how to present it.

Sizing WITHDRAWAL postings

A WITHDRAWAL only checks that its entry does not take the virtual asset’s own balance below zero. It does not check availableBalance. Posting a WITHDRAWAL that ignores outstanding card debt can leave the account with a negative availableBalance — and the master collateral account holding the bag for spend you have already let the user pull off your side. To size a WITHDRAWAL safely, read the withdrawable field on each row of GET /accounts/:id/assets. It is the maximum amount of that virtual asset you can debit without taking availableBalance below zero. Outstanding card debt — including pending authorizations — is netted out, so the value matches what the account can actually release at the moment of the call. withdrawable is a per-asset cap, not a budget that adds up across rows. Each value assumes only that asset is being debited and every other balance stays untouched. Example on an account holding 100 USDC virtual and 500 YUSD virtual with 100ofcarddebtand100 of card debt and 525 of headroom:
  • The USDC row shows withdrawable: "100.000000" (the full balance — well under the $525 cap).
  • The YUSD row shows withdrawable: "500.000000" (the full balance — same headroom, different asset).
You cannot do both. After each posting, call the endpoint again to read the updated caps.

Best practices

Order postings around your actual fund movements

The posting changes Reap’s view of what the user can spend. When the matching change happens on your side matters.
  • DEPOSIT only after on-chain finalization. When the deposit you are mirroring is a chain transfer into your custody, wait for it to be finalized (irreversible), not just confirmed once. If you credit on confirmation and the transfer is later reorged out, you have enabled spend the user cannot back. Plain confirmation depth is not enough on chains that re-org.
  • WITHDRAWAL before the user withdraws. If you debit Reap after letting the user pull funds, the user can race the withdrawal against a card swipe and overspend. Post the WITHDRAWAL first sized via withdrawable; once it returns successfully, you know Reap will reject further spend against that amount, and you can release the funds on your side.
  • SETTLEMENT after card spend is observable. Settle on the CARD_TRANSACTION_UPDATED clearing webhook or on a periodic cadence using liabilities.cardDebt.cleared as the target.

Use the Idempotency-Key header

Every successful posting is a new ledger event, so retries without idempotency double-apply. Pass an Idempotency-Key header with a stable, request-scoped value (UUID v4 is fine) and Reap will return the original result on retry instead of creating a duplicate posting.

One posting per real-world event

A multi-asset deposit on your side becomes one DEPOSIT posting with multiple entries, not one posting per asset. This avoids brief windows where Reap shows half the deposit applied, and keeps every entry in the same atomic ledger event for audit.

What postings are not

  • Not a cap on card spend. Available balance is the cap. Postings feed into available balance but do not block individual transactions on their own.
  • Not a log of your internal movements. Only post when you want Reap’s view of the user’s balance to change. Internal transfers between two of your own buckets do not need a posting.
  • Not how Reap settles with the card network. That happens automatically against the master collateral account. Postings settle the user side: your obligation to the user, and the user’s spend on Reap.