WalletD developers
Guides

Limits and credit lines

Tier caps that refuse money before anything irreversible happens, and credit lines that let a business account spend below zero.

Two controls sit on either side of a wallet's balance. Tier limits cap how much money may flow; credit lines let specific accounts go below zero.

Tier limits

Every user has a tier. A tier carries caps, and the caps are enforced before anything irreversible happens.

curl -sS -X PUT "$WALLETD_API/v1/tier_limits" \
  -H "Authorization: Bearer $WALLETD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tier": "unverified", "max_balance": 3500, "topup_per_day": 5000, "p2p_per_day": 5000}'
curl -sS -X POST "$WALLETD_API/v1/users/$USER_ID/tier" \
  -H "Authorization: Bearer $WALLETD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tier": "unverified"}'

New users are standard unless you say otherwise.

An absent tier row, or a zero field, means unlimited. A tier you never configured constrains nothing. That is the safe default for a platform that has not decided yet, but it does mean "I set a tier" and "I set a limit" are two separate acts.

FieldCaps
max_balanceThe highest cash balance this tier may hold
topup_per_dayMoney in per rolling day
p2p_per_dayMoney sent per rolling day

When they bite

Top-up caps are checked before the processor is called. An over-cap top-up returns 422 tier_limit_exceeded and no payment intent is ever created. The user is not charged for money the wallet was always going to refuse, and you never have to reverse anything.

P2P caps are checked inside the transfer's own transaction, under locks taken in a fixed order. Eight simultaneous sends against a five-send cap land exactly five. You cannot beat the cap by racing it.

Both refusals are 422: the request was understood and permitted, and refused on purpose. Show the user what to do about it, usually "verify your account to raise this limit".

curl -sS "$WALLETD_API/v1/tier_limits" -H "Authorization: Bearer $WALLETD_API_KEY"

Configuration and tier assignment are both audited, with the actor recorded. Neither accepts a user token: a user must never be able to raise their own limit.

Credit lines

A credit line lets one account spend below zero, down to a limit. This is how a business account books inventory before it has been paid.

curl -sS -X POST "$WALLETD_API/v1/users/$USER_ID/credit_limit" \
  -H "Authorization: Bearer $WALLETD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"credit_limit": 500000, "reason": "Q3 agent line, approved by finance"}'

$5,000 of headroom. The user can now spend to -500000 and no further; the next unit over is 422 insufficient_funds, exactly as if they had run out of cash.

Three things to know:

  • available already accounts for it. A user with a zero balance and a $5,000 line has available of 500000. Your existing balance check keeps working.
  • A negative balance is not an error. Do not paint it red just for being below zero. Show the line and the headroom.
  • It is audited and API-key-only. credit:write scope, never a user token, and every change records who did it and why. reason is not decoration; it is what an auditor reads a year later.

credit_limit.changed fires on every change, which is your hook for notifying the account manager.

Where limits sit in the flow

Next

  • Top-ups for the money-in path these caps guard.
  • Transfers for the velocity checks.

On this page