Two classes, never one bucket
A Feddi wallet holds value in two distinct classes. Conflating them is the most common modeling mistake an integrator makes: it overstates the merchant’s real liability. Keep them separate in your own ledger and in anything you render to a cashier.Actual balance (real money)
Funded by customer top-ups. A real deferred-revenue liability the merchant tracks. Spent on
purchases after promotional credit is exhausted.
Promotional credit
Cashback, reload bonus, signup bonus. A contingent class: locked until earned, expirable,
clawback-able, merchant-funded, never cashable. Not a real-money liability.
The Balance object
Every balance Feddi returns exposes both classes distinctly, never a single summed number. Money is always integer minor units paired with an explicit ISO-4217currency.
required
Real money funded by top-ups, in minor units. A real deferred-revenue liability. Spent on purchases
after promotional credit is exhausted.
required
Sum of
remaining_minor across all released, non-expired promotional grants. Spendable now
(promo-first). Not real money.required
Sum of
remaining_minor across all locked promotional grants. Gated on an activation condition (for
example wallet signup or first top-up). Not yet spendable.required
Top-ups in flight, not yet confirmed. Informational only, not spendable.
required
ISO-4217 currency code for all minor-unit fields in this balance, for example
QAR.Wallet identity state. One of
verified or pending_proof. A pending_proof wallet may hold an
actual balance but cannot pay; its cashback-class promo stays LOCKED.Itemized promotional grant breakdown. Each entry carries
source, state, remaining_minor, and
expires_at. May be an empty array on a tight payment result object.Grant
state is uppercase everywhere grants appear (LOCKED, RELEASED, CLAWED_BACK,
EXPIRED), both inside the promo_grants array and in the grant ledger read at
GET /customers/{customerId}/grants. Claim states are a separate machine and stay lowercase.Promo-first debit
When Feddi debits a wallet, it spends promotional credit first (FIFO by expiry across all released grants), then actual balance. The payment result splits the debit explicitly, and the two parts always sum to the amount.required
Total amount debited, in minor units. Equal to
debited_promo_minor + debited_actual_minor.required
Portion drawn from released promo grants (FIFO by expiry). Zero if no promo was available.
required
Portion drawn from the actual (real-money) balance.
The invariant
debited_promo_minor + debited_actual_minor == amount_minor always holds. If actual
plus released promo cannot cover the amount, the call returns INSUFFICIENT_FUNDS (402) and the
credential is not consumed, so you can route to top-up recovery and retry. See
Idempotency and errors.The promo-grant lifecycle
A promotional grant moves through a small state machine. In the grant ledger, the four states are uppercase.required
One of
LOCKED, RELEASED, CLAWED_BACK, EXPIRED.LOCKED: accrued but gated. Cashback accrues on every transaction, including cash and card purchases, as locked promo. The customer signs up or tops up to unlock it.RELEASED: spendable. Released only when the customer is verified and the merchant’s claim-gate condition is met. See PENDING_PROOF and promo release.CLAWED_BACK: reversed. For example, reversing a top-up that earned a bonus claws the bonus back. A clawback that hits already-spent promo books the spent portion as a merchant marketing loss; it is never pulled from the customer’s actual cash. This is a terminal state.EXPIRED: past its own clock. Promo expires on a merchant-configured schedule (for example, three months), independent of actual balance. This is a terminal state.
The grant
source is one of CASHBACK, RELOAD_BONUS, SKU_TOPUP_BONUS, GATEWAY_BONUS, or
SIGNUP_BONUS. Treat the set as open: read GET /capabilities and validate against the served
OpenAPI spec rather than hard-coding it.Accounting for the two classes
Promotional credit is accounted separately from the real-money float. Actual balance is a real liability (deferred revenue the merchant owes as goods or services). Promotional credit is a contingent promotional cost, not a settled obligation, because until it is released the customer cannot spend it. Treating the two as one bucket would overstate what the merchant owes.Where to go next
PENDING_PROOF and promo release
How locked promo gets released safely, only on verified phone proof.
Top-up and reload bonus
Crediting actual balance and accruing reload-bonus promo.
Payments and redemption
The promo-first debit endpoint in detail.
Incentives
Read the promo-grant ledger and claw back a grant.