Wallet
Fees

Fees

Who calls these endpoints?External API (s2s)
Base path
/api/v1/wallet
Identity
Ed25519 request signature — X-Key-Id, X-Date, X-Nonce, Digest (when there is a body), X-Signature. ±5 min clock window, single-use nonce, optional per-key IP allow-list.
Authorization
The key must carry the wallet product and the wallet permission the call requires; a call without it gets 403 WALLET_INSUFFICIENT_SCOPE. Permissions per endpoint: Key permissions.
Cross-surface
POST fees/quote exists on all three surfaces (s2s, portal, panel). Managing fee and commission SCHEDULES is panel-only — 17 endpoints, wallet:fee:manage, version submit/approve chain and four-eyes.

Wallet fees are defined by a schedule and computed per operation with a quote. There is one core rule:

⚠️

What is quoted is what is charged. The amount you show the user in the quote must equal the amount that leaves the account. This is not advice but a platform-enforced constraint: the initiate step fixes the amounts in the operation's integrityHash, the complete step verifies it, and a mismatch rejects the operation.

Quoting a fee

POST /api/v1/wallet/fees/quote
FieldTypeRequiredDescription
programIdstring✅
operationTypestring✅Which operation type
currencystring✅
amountstring✅Minor-unit transaction amount
atstring—Compute as of a given instant (ISO date)
{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "feeAmount": "250",
    "constantPart": "100",
    "percentagePart": "150",
    "percentageBps": 15,
    "expenseAmount": "0",
    "taxLegs": [{ "name": "BSMV", "amount": "125" }],
    "taxTotal": "125",
    "totalCharge": "10425",
    "scheduleVersionId": "2d8b5e1c-7f4a-4c9e-a3b6-8e1f5c2d9a74",
    "appliedTimeKey": "WEEKDAY",
    "appliedThreshold": "10000"
  }
}
FieldMeaning
feeAmountTotal fee (fixed + percentage)
constantPartFixed component
percentagePartPercentage component
percentageBpsApplied rate in basis points (15 bps = 0.15%)
expenseAmountExpense component
taxLegsTax lines — name and amount
taxTotalTotal tax
totalChargeTotal leaving the account (amount + fee + tax)
scheduleVersionIdSchedule version used
appliedTimeKeyWhich time-of-day/week rule applied
appliedThresholdWhich amount-threshold branch was taken

Show the user totalCharge, not amount. If "send ₺100" will debit ₺104.25, they must see that before sending.

Pinning the schedule version

If you send the quote's scheduleVersionId back when initializing, the fee is pinned to that version. Omit it and the schedule current at execution time applies.

{
  "endUserId": "8d4c2a1f-3b6e-4f7a-9c5d-2e8b1a0f6c34",
  "sourceWalletAccountId": "c2a5e8f1-9d3b-4c7a-8e6f-5b1d2a9c0e47",
  "destinationPhone": "+905339876543",
  "amount": "10050",
  "currency": "TRY",
  "scheduleVersionId": "2d8b5e1c-7f4a-4c9e-a3b6-8e1f5c2d9a74"
}
⚠️

When a long time can pass between quote and execute (the user left the screen open), sending scheduleVersionId is the correct behaviour — otherwise the fee the user saw and the fee charged diverge, and the operation is rejected at integrityHash verification.

How the fee is computed

A fee schedule is a matrix: at the intersection of operation type × currency it branches by amount thresholds and time windows.

Fee calculation pipelineProcess: operation type, currency, amount band and time window select a fee branch; its fixed and rate components are computed, tax is added on top and the total charge comes out.Branch selectiontype · currency · band · timeFixed + rate (bps)TaxtotalChargeLEGENDCOMPUTE STEPSHOWN TO THE USER
Show the user totalCharge, not amount: that is what actually leaves the account, fee and tax included. The scheduleVersionId in the quote pins the fee you displayed.

appliedThreshold and appliedTimeKey tell you which branch the quote landed on — the first place to look when a fee surprises you.

Fees vs commission

FeeCommission
Charged toThe user performing the operationThe collecting business
Where it appearsfeeTotalcommissionTotal
ScheduleFee scheduleCommission schedule

Both can occur on one operation: the user pays a fee while the business pays collection commission.

Schedule management and approval

Fee schedules are versioned and approved:

Four-eyes approval chainState machine: a draft is submitted, waits for approval, becomes active once approved and is retired at the end of its life. A rejected draft ends on its own branch.SUBMITAPPROVERETIREREJECTDRAFTPENDING_APPROVALACTIVERETIREDREJECTEDLEGENDWAITINGIN FORCEEND
The same chain governs fee schedules, limit schemes and sponsor policy. The approver must differ from the submitter — four-eyes is enforced in the service layer, not in the UI.

The person who drafts and the person who approves must differ. An approved version becomes active and the previous one retires; past operations stay traceable through their own scheduleVersionId.

Panel side: Panel — Limit & Fee Schemes.

End-user surface

POST /api/portal/v1/wallet/fees/quote

The same computation, under the user's own session. Call it as the amount is typed so the fee updates live in your app.

Common mistakes

SymptomCauseFix
"More was charged than I expected"You displayed amount instead of totalChargeShow the total on screen
Operation rejected on integrityHashThe schedule changed between quote and executeSend scheduleVersionId
Fee lands on an unexpected branchDifferent amount threshold or time windowInspect appliedThreshold and appliedTimeKey
No tax showntaxLegs is emptyThe schedule defines no tax component