Skip to main content

Leases

The owner buys an asset, keeps title to it, and rents out its use. Rent is earned for the use of a thing that exists and is owned — not for the passage of time over a sum of money.

Ownership is not a formality here: it comes with costs. Insurance, major repairs, the risk that the asset is destroyed — these sit with the owner for as long as the owner holds title, and the API has a dedicated transition for recording them. A lease in which the user bears every ownership cost while the owner bears none is a loan against collateral, described in leasing vocabulary.

Base path: /api/v1/pfp/leases · Religious reading: Ijara


Two forms​

lease_typeEnds withPurchase option
operatingThe asset comes back to the ownerNone
financeTitle passes to the lesseeMandatory — purchase_option_price is required at creation

The form determines which ending is legal. An operating lease cannot be closed by transfer of ownership, and a finance lease cannot be closed by return — closing a finance lease by return would strip the lessee of the purchase right it has been paying towards. The API refuses both.

Choosing finance sets purchase_option to true automatically and makes purchase_option_price required and positive.


Statuses​

draft ──submit──> under_review ──review──> review_passed
│ │ │
│ └──reject──> rejected │
│ │
└──────────── acquire ────────────────────────┘
│
v
asset_acquired ──activate──> active
│
┌──────────────────────────┼──────────────────┐
│ (finance) │ (operating) │
v v v
transfer_pending ──transfer──> completed terminated
^
└── return (operating)
StatusMeaning
draftTerms recorded
under_reviewSubmitted for approval
review_passedA conclusion is attached
rejectedTerminal. Requires a reason
asset_acquiredThe owner holds title and the ownership documents
activeThe asset is with the lessee; rent is running
transfer_pendingFinance lease only — the term is over, title transfer is being formalised
completedReturned (operating) or transferred (finance)
terminatedEnded early. Requires a reason

In the secular reading acquire is reachable from draft as well as review_passed.


Create a lease​

POST /api/v1/pfp/leases
{
"customer_id": "8f2a1c44-0b6e-4d51-9a3f-1c8e5b7d2a90",
"region": "RU",
"currency": "RUB",
"lease_type": "finance",
"asset_type": "equipment",
"asset_description": "CNC milling machine DMG MORI CMX 1100 V",
"asset_cost": "1450000000",
"lease_term_months": 48,
"monthly_rental": "3600000",
"advance_rental": "7200000",
"security_deposit": "10000000",
"residual_value": "290000000",
"purchase_option_price": "290000000",
"asset_location": "Kazan, Industrial Park B"
}
FieldTypeRequiredNotes
customer_iduuid✅The lessee
regionstring✅Contract region
lease_typeenum✅operating | finance
asset_descriptionstring✅The asset must exist and be identifiable at signing
asset_coststring✅Minor units, above zero
lease_term_monthsinteger✅1–240 periods of 30 days
monthly_rentalstring✅Minor units, above zero
purchase_option_pricestringconditionalRequired when lease_type is finance
asset_typeenum—vehicle | equipment | real_estate | aircraft | vessel | machinery
advance_rentalstring—Paid up front, added to the total due
security_depositstring—Held, not rent
residual_valuestring—Expected value at term end
asset_serial_number, asset_location, asset_specifications——Identification of the specific thing
currency, product_id, metadata——

The asset must be identifiable. asset_description must be substantive — anything ten characters or shorter is refused. This is not pedantry: renting out an unspecified future object is a bet, not a lease, and the contract would be void in the jurisdictions this product is built for. Use asset_serial_number and asset_location to pin down the specific thing.

total_rentals_due is derived: monthly_rental × lease_term_months + advance_rental.


Acquire the asset​

POST /api/v1/pfp/leases/{id}/acquire
{
"ownership_documents": ["purchase-invoice-8812.pdf", "customs-decl-4471.pdf"],
"asset_serial_number": "DMG-CMX1100V-2026-0417",
"asset_registration": "RU-EQ-2026-88120",
"insurance_policy": "SOGAZ-EQ-2026-11904",
"insurance_expires": "2027-09-01"
}

ownership_documents is required — a non-empty list. This is the transition that records that the owner actually owns the thing, and it will not accept an empty hand.

draft or review_passed → asset_acquired.


Hand over and start​

POST /api/v1/pfp/leases/{id}/activate
{ "delivery_date": "2026-09-15" }

delivery_date is optional and defaults to today. The lease term and the whole payment schedule are counted from it — rent starts when the lessee gets the asset, not when the contract was signed.

asset_acquired → active.

The schedule​

Generated at activation. The first row falls one period after the start date, not on it: rent is paid for a month of use that has already happened.

{
"payment_schedule": [
{ "payment_number": 1, "due_date": "2026-10-15", "amount": "3600000", "status": "pending" },
{ "payment_number": 2, "due_date": "2026-11-14", "amount": "3600000", "status": "pending" }
]
}

Periods are 30 days, so due dates drift relative to the calendar. Every row carries the full monthly_rental — unlike an instalment sale, nothing is divided here, so there is no rounding remainder. The schedule therefore sums to monthly_rental × lease_term_months; advance_rental, if any, is on top of it and is not a schedule row.


Running the lease​

Rent received​

POST /api/v1/pfp/leases/{id}/payment
{ "amount": "3600000" }

Adds to total_rentals_paid and advances the schedule.

Arrears​

POST /api/v1/pfp/leases/{id}/arrears
{ "amount": "7200000" }

Records the overdue amount. Zero is a valid value and clears the delinquency — this is the one amount field in the product family that accepts "0" (^(0|[1-9]\d*)$ rather than ^[1-9]\d*$).

As with instalment sales, recording arrears does not add anything to what is owed.

Owner's expense​

POST /api/v1/pfp/leases/{id}/expense
{
"amount": "4500000",
"description": "Spindle bearing replacement, works order 2211",
"type": "maintenance"
}

This is the transition that makes the owner an owner. Insurance premiums, major repairs, statutory inspections — the costs that follow title rather than use.

description is required and must not be blank. An expense with no stated purpose cannot be justified to the lessee, and it is exactly that justification which distinguishes an owner's cost from a charge quietly passed through to the lessee. type defaults to maintenance.

Expenses accumulate in total_owner_expenses and are listed in owner_expenses.


Ending the lease​

Which ending is available depends on lease_type.

Operating lease — return​

POST /api/v1/pfp/leases/{id}/return

No body. active → completed, and return_date is set to today. Refused on a finance lease.

Finance lease — transfer of title​

Two steps, because the term ending and the paperwork completing are not the same day.

POST /api/v1/pfp/leases/{id}/transfer_pending

No body. active → transfer_pending. Refused on an operating lease.

POST /api/v1/pfp/leases/{id}/transfer

No body. Moves the contract to completed and sets transfer_date.

Two conditions are enforced, and both matter:

  • The lease must be a finance lease.
  • The rent must be paid in full. If total_rentals_paid is short of total_rentals_due, the transfer is refused and the response names the outstanding amount:
{
"error": "unprocessable_entity",
"details": {
"total_rentals_paid": ["аренда выплачена не полностью: остаток 7200000"]
}
}

transfer is reachable from both active and transfer_pending, so the intermediate step can be skipped when the paperwork is immediate.

Early termination​

POST /api/v1/pfp/leases/{id}/terminate
{ "reason": "Lessee ceased operations" }

Only an active lease can be terminated. A lease already completed by transfer or return cannot be moved to terminated — that would erase the record of an ending that actually took place.


List and read​

GET /api/v1/pfp/leases
Query parameterValues
statusany status above
regioncontract region
typeoperating | finance
customer_iduuid
arrearstrue — only active leases currently in arrears
ending_in_daysinteger — only active leases whose term ends within N days
envtest | prod

The last two are built for operational review: ?arrears=true gives the collections queue, ?ending_in_days=60 gives the leases needing a renewal or transfer decision this quarter.

GET /api/v1/pfp/leases/{id}