Skip to main content

Safekeeping Deposits

A demand account. The holder puts money in, takes it out whenever they want, and the amount is guaranteed — no return is promised, and none is owed.

The account may still pay something. POST /bonus records a payment to the holder, and that is exactly what it is called: a bonus, not a return. It is the account-keeper's right, not the holder's entitlement. Its size is decided when it is paid; it is not announced in advance, not accrued, and not owed. An amount promised in advance would be interest with a friendlier name, and the product would become a different product.

Two consequences for your integration: there is no rate field anywhere on this account, and there is no approval stage — a demand account opens without a third party's conclusion in either reading.

Base path: /api/v1/pfp/safekeeping-deposits · Religious reading: Wadiah


Two custody forms

custody_typeThe keeper may use the fundsPrincipal
safekeeping_onlyNo — pure custodyHeld, untouched
guaranteedYesGuaranteed at face value

guaranteed is the ordinary current-account arrangement: the funds are used, and the holder is guaranteed to get back exactly what was put in. safekeeping_only is custody in the strict sense.

The response carries a derived boolean guaranteed alongside custody_type, so you do not have to know which enum value implies the guarantee.


Statuses

pending ──activate──> active ──block──> blocked
│ <──unblock──┘

└──close──> closed
StatusMeaning
pendingCreated, not yet open
activeOpen; deposits, withdrawals and bonuses are accepted
blockedFrozen. Requires a reason
closedTerminal

There is no under_review, no review_passed and no rejected. This product has no approval stage in either reading — a transition asking for one would mean the account had been confused with a financing contract.


Open an account

POST /api/v1/pfp/safekeeping-deposits
{
"customer_id": "8f2a1c44-0b6e-4d51-9a3f-1c8e5b7d2a90",
"region": "RU",
"currency": "RUB",
"custody_type": "guaranteed",
"initial_amount": "0",
"minimum_balance": "100000",
"account_id": "d4b7e211-8c05-4f39-a6be-7213c9e0f584",
"opened_by": "branch-kzn-04"
}
FieldTypeRequiredNotes
customer_iduuidThe holder
regionstringAccount region
currencystringISO 4217
custody_typeenumsafekeeping_only | guaranteed
initial_amountstringMinor units. Zero is allowed (^\d+$)
minimum_balancestringMinor units. Zero allowed
account_iduuidA linked operational account
opened_bystringFree text
metadataobjectReturned untouched

initial_amount and minimum_balance are the two amount fields in this product family that accept "0". An account is often opened empty and funded afterwards, and a threshold of zero is a real setting.

Note the difference between the two zeros in a response: "minimum_balance": null means there is no minimum, "minimum_balance": "0" means the minimum is zero. current_balance is never null — a newly opened account has a balance of "0", not an absent one.


Money in and out

All three require the account to be active. On a pending, blocked or closed account they are refused.

Deposit

POST /api/v1/pfp/safekeeping-deposits/{id}/deposit
{ "amount": "50000000" }

Adds to current_balance and total_deposits, increments transactions_count.

Withdraw

POST /api/v1/pfp/safekeeping-deposits/{id}/withdraw
{ "amount": "12000000" }

Adds to total_withdrawals. Refused if it would take the balance below minimum_balance.

Bonus

POST /api/v1/pfp/safekeeping-deposits/{id}/bonus
{ "amount": "180000", "reason": "Year-end appreciation" }

amount is required, reason optional. Accumulates in total_bonus_received and appends to bonus_history.

This is a payment made at the keeper's discretion. Nothing in the account announces it in advance, and a holder who receives one this year has no claim to one next year.


Freezing and closing

POST /api/v1/pfp/safekeeping-deposits/{id}/activate    # no body, pending → active
POST /api/v1/pfp/safekeeping-deposits/{id}/block # reason required
POST /api/v1/pfp/safekeeping-deposits/{id}/unblock # no body
POST /api/v1/pfp/safekeeping-deposits/{id}/close # closed_by optional

List and read

GET /api/v1/pfp/safekeeping-deposits
Query parameterValues
statuspending | active | blocked | closed
regionaccount region
customer_iduuid
typesafekeeping_only | guaranteed
min_balanceminor units, ^\d+$ — accounts at or above this balance
envtest | prod

An omitted filter adds no condition. Sending an empty string for one — which is what an unfilled form field produces — is treated the same way, so a partially filled search form does not collapse the result set to nothing.

GET /api/v1/pfp/safekeeping-deposits/{id}
{
"data": {
"id": "7c0b8a1e-0a5e-4a3f-9b6d-2f1f3a4b5c6d",
"deposit_number": "SFK-G-RU-20260823-1B4E07",
"status": "active",
"custody_type": "guaranteed",
"guaranteed": true,
"currency": "RUB",
"current_balance": "38180000",
"initial_amount": "0",
"minimum_balance": "100000",
"total_deposits": "50000000",
"total_withdrawals": "12000000",
"total_bonus_received": "180000",
"bonus_history": [
{ "date": "2026-12-31", "amount": "180000", "reason": "Year-end appreciation" }
],
"bonus_rate_annualized": 0,
"transactions_count": 3
}
}

bonus_rate_annualized is a rear-view mirror

The response includes an annualised figure for the bonuses actually paid, computed from the account's age. It is a report on the past, not a rate. It appears only once the account has an opening date; before then it is 0.

Do not present it to a holder as what the account pays. Nothing about a bonus paid last year commits anyone to a bonus next year, and a number displayed next to a percent sign will be read as a promise no matter what label sits beside it.