Charges API
Manage service charges (charges locatives) for leases — heating, water, elevator maintenance, common area upkeep, and other recurring costs billed to tenants. The charge system enforces French regulatory compliance (Décret n°87-713) with billing mode validation, calculation basis rules, lease type compatibility, freeze periods, and annual regularization workflow.
Quick Example
Code
Common Workflows
Set up charges for a new lease
- Create place services for the building
- Choose or create distribution keys
POST /api/leases/{id}/charges— attach charges to the leasePOST /api/charges/readings— record meter readings over timePOST /api/leases/{id}/charges/{id}/regularize— perform annual settlement
Annual charge settlement (régularisation)
GET /api/charges/readings— get all readings for the periodPOST /api/leases/{id}/charges/reviews— create an annual reviewPOST /api/leases/{id}/charges/reviews/{id}/details— add detail lines per chargePOST /api/leases/{id}/charges/reviews/{id}/transition— advance through status workflowPOST /api/leases/{id}/charges/{id}/regularize— record the settlement per charge- Or use
POST /api/leases/{id}/charges/finalize— bulk settlement at lease end
Generate rent receipts (quittances)
Once charges are set up, generate monthly rent receipts that separate rent and charges as required by Art. 21 Loi 89-462:
POST /api/leases/{id}/receipts/generate— generate receipts for all active tenantsGET /api/leases/{id}/receipts/{receipt_id}/pdf— download the PDF
See the full Rent Receipts guide for details.
Authentication
All endpoints require authentication:
- LeasesRead: GET operations
- LeasesWrite: POST and PUT operations
- LeasesDelete: DELETE operations
Charge Categories
Categories classify charges according to Décret n°87-713, which defines recoverable charges for residential leases.
Category Types
| Value | Description | Recovery Rate | Legal Reference |
|---|---|---|---|
EMPLOYEE | Building employee costs (concierge, gardien) | 75%, 40%, or 100% (see below) | Décret 87-713, Article 2 |
ELEVATOR | Elevator operation and maintenance | 100% | Décret 87-713, Annexe, I |
HEATING | Collective heating and hot water production | 100% | Décret 87-713, Annexe, II |
WATER | Cold water and sanitation | 100% | Décret 87-713, Annexe, II |
INDIVIDUAL_EQUIPMENT | Equipment specific to the tenant's unit | 100% | Décret 87-713, Annexe, III |
COMMON_AREAS | Common area maintenance (interior lighting, green spaces) | 100% | Décret 87-713, Annexe, IV & V |
CLEANING | Hygiene and common area cleaning | 100% | Décret 87-713, Annexe, VI |
MAINTENANCE | General maintenance and small repairs | 100% | Décret 87-713, Annexe, VII |
TAXES | Taxes and fees (TEOM, sweeping tax) | 100% | Décret 87-713, Annexe, VIII |
Note on EMPLOYEE recovery rates: The rate depends on the employee's situation:
- 75% — Gardien/concierge performing both common area maintenance and waste disposal (Article 2, Décret 87-713)
- 40% — Gardien/concierge performing only one of those two tasks
- 100% — Non-resident building employee (employé d'immeuble not housed on-site)
The API applies the correct rate based on the
PERSONNEL_*calculation basis selected.
Category-Basis Constraint
The EMPLOYEE category has a special coupling with personnel calculation bases:
EMPLOYEEcharges MUST use aPERSONNEL_*calculation basis (PERSONNEL_75_POURCENT,PERSONNEL_40_POURCENT, orPERSONNEL_100_POURCENT). UsingFORFAITorDEPENSE_REELLEwithEMPLOYEEreturns400 Bad Request.PERSONNEL_*bases can ONLY be used with theEMPLOYEEcategory. Using them with any other category returns400 Bad Request.
Endpoints
List Categories
GET /api/charges/categories
Query Parameters:
category_type(optional): Filter by category type
Response: 200 OK
Code
Create Category
POST /api/charges/categories
Request Body:
Code
Response: 201 Created
Get Category
GET /api/charges/categories/{id}
Response: 200 OK
Update Category
PUT /api/charges/categories/{id}
Response: 200 OK
Delete Category
DELETE /api/charges/categories/{id}
Response: 204 No Content
Lease Charges
A lease charge links a lease to a place service, a charge category, and a distribution key. It defines the billing mode, calculation basis, and amount for one specific charge line on the lease.
LeaseCharge Model
| Field | Type | Required | Description |
|---|---|---|---|
id | UUID | auto | Unique identifier |
lease_id | UUID | yes | The lease this charge belongs to |
service_place_id | UUID | no | The place service being charged |
category_id | UUID | no | The charge category |
distribution_key_id | UUID | no | How costs are split — resolved from service default if not provided |
calculation_method | BillingMode | yes | How the tenant is billed |
calculation_basis | CalculationBasis | yes | How the amount is determined |
amount | decimal | yes | Charge amount in euros |
billing_period_start | date | no | Billing period start |
billing_period_end | date | no | Billing period end |
last_regularization_date | date | no | Date of last annual settlement |
notes | string | no | Additional notes (required for increases >20%) |
created_at | datetime | auto | Creation timestamp |
updated_at | datetime | auto | Last update timestamp |
Distribution Key Resolution
When creating a charge, the distribution key is resolved in order:
- Explicit
distribution_key_idin the request body default_distribution_key_idfrom the linked service place- If neither is available, the request fails with
400 Bad Request
Endpoints
List Charges for a Lease
GET /api/leases/{lease_id}/charges
Response: 200 OK
Code
Create Charge
POST /api/leases/{lease_id}/charges
The API runs a full validation pipeline before creating the charge (see Validation Rules).
Request Body:
Code
You can also embed specialized charge data inline:
Code
Response: 201 Created
Get Charge
GET /api/leases/{lease_id}/charges/{charge_id}
Response: 200 OK
Update Charge
PUT /api/leases/{lease_id}/charges/{charge_id}
All fields are optional for partial updates. If the charge amount increases by more than 20%, the notes field becomes mandatory (min 10 characters).
Response: 200 OK
Delete Charge
DELETE /api/leases/{lease_id}/charges/{charge_id}
Response: 204 No Content
Regularize Charge
POST /api/leases/{lease_id}/charges/{charge_id}/regularize
Perform the annual settlement (régularisation) for a provisioned charge. Records the actual expense and calculates the difference.
Request Body:
Code
Response: 200 OK
Billing Modes
The billing mode (calculation_method) defines how the tenant is invoiced for a charge.
| Value | Description | Settlement |
|---|---|---|
FORFAIT | Fixed amount — tenant pays a flat fee regardless of actual cost | No annual settlement. Amount is final. |
PROVISION | Provisional monthly payments, adjusted at year-end | Annual settlement (régularisation) required. Tenant pays or is credited the difference. |
DEPENSE_REELLE | Actual expense — tenant pays exact costs incurred | Billed after the expense occurs. |
RELEVE_DIRECT | Direct meter reading — tenant pays based on individual consumption | Billed per reading period. |
When to use each mode
- FORFAIT: Ideal for furnished leases where the law allows a fixed charge amount. No obligation to justify actual costs.
- PROVISION: Standard for unfurnished residential leases. Monthly provisions with annual regularization.
- DEPENSE_REELLE: Used when costs are invoiced to the building and redistributed. Common for co-ownership charges.
- RELEVE_DIRECT: When tenants have individual meters (electricity, gas). The charge tracks what each tenant actually consumes.
Calculation Basis
The calculation basis defines how the charge amount is determined.
| Value | Description | Category Restriction |
|---|---|---|
FORFAIT | Fixed amount agreed in the lease | Any category except EMPLOYEE |
DEPENSE_REELLE | Based on actual documented expenses | Any category except EMPLOYEE |
PERSONNEL_75_POURCENT | 75% of personnel costs (concierge: cleaning + trash) | EMPLOYEE only |
PERSONNEL_40_POURCENT | 40% of personnel costs (single task, e.g. waste disposal only) | EMPLOYEE only |
PERSONNEL_100_POURCENT | 100% of personnel costs (non-resident building employee) | EMPLOYEE only |
Billing Mode × Calculation Basis Compatibility
Not all combinations of billing mode and calculation basis are valid. The API enforces the following matrix — invalid combinations return 400 Bad Request.
| Billing Mode | Allowed Calculation Bases |
|---|---|
| FORFAIT | FORFAIT |
| PROVISION | All bases (FORFAIT, DEPENSE_REELLE, PERSONNEL_75_POURCENT, PERSONNEL_40_POURCENT, PERSONNEL_100_POURCENT) |
| DEPENSE_REELLE | DEPENSE_REELLE, PERSONNEL_75_POURCENT, PERSONNEL_40_POURCENT, PERSONNEL_100_POURCENT |
| RELEVE_DIRECT | FORFAIT |
Distribution Type × Billing Mode Constraint
An additional rule applies when using ConsommationMesuree distribution keys:
ConsommationMesureedistribution requiresRELEVE_DIRECTorPROVISIONbilling mode- Other distribution types allow
PROVISIONorFORFAIT DEPENSE_REELLEbilling mode accepts all distribution types
Examples
| Scenario | Billing Mode | Calculation Basis |
|---|---|---|
| Furnished lease, fixed monthly charges | FORFAIT | FORFAIT |
| Unfurnished lease, monthly water provision | PROVISION | FORFAIT |
| Concierge costs, provisioned monthly | PROVISION | PERSONNEL_75_POURCENT |
| Co-ownership charges billed at actuals | DEPENSE_REELLE | DEPENSE_REELLE |
| Individual electricity meter | RELEVE_DIRECT | FORFAIT |
Lease Type × Charge Compatibility
Different lease types have different rules for which charge categories and billing modes are allowed. This is configured per lease type via LeaseTypeChargeConfig.
| Lease Type | Allowed Categories | Forfait Allowed | Provision Allowed | Annual Review Required | Max Provisional Months |
|---|---|---|---|---|---|
| Bail habitation nue | All residential | No | Yes | Yes | 12 |
| Bail meublé | All residential | Yes | Yes | Yes | 12 |
| Bail mobilité | All residential | Yes (mandatory) | No | No | — |
| Bail commercial | All + commercial | Yes | Yes | Per contract | Per contract |
| Bail professionnel | All + professional | Yes | Yes | Per contract | Per contract |
| Colocation | All residential | Yes | Yes | Yes | 12 |
Key Rules
- Bail habitation nue (unfurnished residential): Forfait billing is not allowed — charges must be provisioned with annual regularization. This is a legal requirement.
- Bail meublé (furnished): Both forfait and provision are allowed. Forfait is common for simplicity.
- Bail mobilité (mobility lease): Only forfait is allowed — no provisions, no regularization. The lease is short-term (1–10 months).
- Bail commercial / professionnel: Rules are more flexible and governed by the lease contract rather than statute.
Charge Settlement Modes
At the lease level, a ChargeSettlementMode governs how all charges on that lease are billed together.
| Value | Description | Required Billing Mode |
|---|---|---|
PROVISION | Provisional with annual regularization | All charges must be PROVISION |
PERIODIC | Periodic payment of actual costs | All charges must be DEPENSE_REELLE or RELEVE_DIRECT |
FLAT_RATE | Fixed charge amount | All charges must be FORFAIT |
The API validates that every individual charge billing mode matches the lease-level settlement mode. Mismatches return 400 Bad Request.
Settlement mode availability by lease type:
- Lease types configured with
LeaseChargeMode::ProvisionallowPROVISIONandPERIODICsettlement (but notFLAT_RATE) - Lease types configured with
LeaseChargeMode::Forfaitallow all three settlement modes
Validation Rules
When creating or updating a lease charge, the API runs the following validation pipeline in order:
1. Lease Status Check
Charges can only be created/modified on leases with status Active, Draft, or Notice. Terminated or expired leases return 422.
2. Freeze Period Check
If an active charge freeze period exists for the charge's category and country, modifications are blocked. See Charge Freeze Periods.
3. Distribution Key Resolution
See Distribution Key Resolution above.
4. Distribution Type × Billing Mode Compatibility
ConsommationMesuree distribution keys require RELEVE_DIRECT or PROVISION.
5. Billing Mode × Calculation Basis Compatibility
See the compatibility matrix.
6. Category × Basis Coupling
EMPLOYEE ↔ PERSONNEL_* exclusive coupling.
7. Lease Type Compatibility
The charge category must be allowed for the lease type. The billing mode must be permitted.
8. Billing Period Validation
billing_period_startmust be ≤billing_period_end- Periods must fall within the lease's start/end dates
- For
PROVISIONmode, period cannot exceedmax_provisional_months
9. No Period Overlap
Two charges for the same service/category cannot have overlapping billing periods.
10. Regularization Requirements
If the lease type requires annual review and the billing mode is PROVISION:
last_regularization_datemust be within the last 12 months
11. Charge-to-Rent Ratio Warnings
The API issues non-blocking warnings when charges appear disproportionate relative to rent (these are business safeguards, not legal limits):
- Residential leases (habitation nue/meublé): warning if total charges > 40% of rent
- Commercial leases: warning if total charges > 50% of rent
12. Documentation Requirement
When updating a charge with an increase > 20%, the notes field is required (minimum 10 characters explaining the reason).
13. Service-Lease Compatibility
When a service_place_id is provided:
- The service's
place_idmust match the lease's estate'splace_id - The service must have
is_chargeable = true - The service's category must be allowed for the lease type
Charge Freeze Periods
Regulatory freeze periods temporarily block charge modifications for specific categories and countries.
FreezePeriod Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
freeze_type | FreezeType | Type of freeze |
category_id | UUID | Affected charge category (or all) |
country_id | UUID | Affected country/legislative zone |
start_date | date | Freeze start |
end_date | date | Freeze end |
max_increase_percentage | decimal | Maximum allowed increase (for INCREASE_LIMIT type) |
legal_reference | string | Legal basis for the freeze |
conditions | JSONB | Additional conditions |
exceptions | JSONB | Cases exempt from the freeze |
Freeze Types
| Value | Description |
|---|---|
TOTAL_FREEZE | All charge modifications blocked |
PARTIAL_FREEZE | Some modifications blocked (conditions apply) |
INCREASE_LIMIT | Increases limited to a percentage |
SEASONAL_FREEZE | Freeze active during specific seasons (e.g., winter truce) |
Charge Regulations (Adjustments)
When charges are adjusted due to freeze periods, legal caps, or exceptions, the system records a ChargeRegulation.
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
lease_charge_id | UUID | The affected charge |
regulation_type | RegulationType | Type of regulation |
original_amount | decimal | Amount before adjustment |
adjusted_amount | decimal | Amount after adjustment |
adjustment_details | JSONB | Justification and details |
Regulation Types
| Value | Description |
|---|---|
FREEZE | Adjustment due to an active freeze period |
LEGAL_EXCEPTION | Exception to normal rules (e.g., court order) |
Required fields by regulation type:
- When
regulation_type = FREEZE, thefreeze_period_idfield is required.- When
regulation_type = LEGAL_EXCEPTION, thelegal_exception_idfield is required.
Charge Reviews (Régularisation Annuelle)
The annual review process compares provisional charges against actual expenses.
ChargeReview Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
estate_id | UUID | The estate being reviewed |
year | integer | Year under review |
status | ReviewStatus | Current workflow status |
total_provisional_amount | decimal | Total provisions collected |
total_actual_amount | decimal | Total actual expenses |
total_difference_amount | decimal | Difference (positive = tenant owes, negative = credit) |
Review Status Workflow
Code
| Status | Description |
|---|---|
DRAFT | Review created, not yet started |
IN_PROGRESS | Actual expenses being collected |
PENDING_VALIDATION | Expenses entered, awaiting validation |
VALIDATED | Amounts confirmed by the manager |
SENT | Settlement notice sent to tenant |
DISPUTED | Tenant has disputed the settlement |
CLOSED | Review complete, adjustments applied |
Legal Requirements (Art. 23 Loi 89-462)
- Annual regularization is mandatory for provisioned charges
- The landlord must communicate the itemized breakdown to the tenant 1 month before the regularization
- Supporting documents must be available to the tenant for 6 months after the regularization notice
- Unpaid charges can be claimed for up to 3 years (Art. 7-1 Loi 89-462)
Specialized Charges
Energy Efficiency Contribution (Contribution au partage des économies d'énergie)
When a landlord performs energy-efficient renovations, they may bill tenants a monthly contribution under certain conditions (Art. 23-1 Loi 89-462, Décret 2009-1439):
- The works must consist of a bouquet de travaux (combination of at least 2 energy improvement actions) or achieve a global energy performance threshold
- The contribution cannot exceed 50% of the estimated monthly energy savings
- The contribution is limited to 15 years after the renovation
- The contribution is fixed and non-revisable (forfaitaire) for private-sector landlords
- A concertation procedure with the tenant is required before charging
- Building restrictions: pre-1948 buildings can only use the work package option; post-1990 buildings are excluded entirely
Model fields:
| Field | Type | Description |
|---|---|---|
baseline_consumption | decimal | Energy consumption before works |
target_savings_percentage | decimal | Expected savings percentage (0–100) |
monthly_contribution_amount | decimal | Monthly amount charged to tenant |
remaining_months | integer | Months remaining for the contribution |
work_description | string | Description of the energy improvement works (min 10, max 1000 chars) |
work_cost | decimal | Total cost of the works |
energy_audit_reference | string | Reference to the energy audit/DPE report |
start_date | date | Contribution start date |
end_date | date | Contribution end date (computed: start + duration × 30 days) |
Create inline with a lease charge:
Code
Colocation Insurance (Assurance colocation)
For shared-tenancy leases (colocation), the landlord may subscribe to a group insurance policy and recover the cost from tenants.
Model fields:
| Field | Type | Description |
|---|---|---|
contract_number | string | Insurance policy number |
insurance_company | string | Insurance provider name |
annual_premium | decimal | Total annual premium |
recoverable_amount | decimal | Amount recoverable from tenants |
coverage_details | string | Coverage description |
policy_start_date | date | Policy start |
policy_end_date | date | Policy end |
deductible_amount | decimal | Policy deductible |
coverage_limits | JSONB | Coverage limits by type |
exclusions | string | Policy exclusions |
Validation rules:
annual_premiummust be > 0recoverable_amountmust be > 0 and ≤annual_premiumpolicy_end_datemust be afterpolicy_start_datecoverage_detailsmust be 10–500 characters
The response includes computed fields:
monthly_recoverable:annual_premium / 12is_policy_active:trueif today falls betweenpolicy_start_dateandpolicy_end_date
Create inline with a lease charge:
Code
Charge Readings
Readings track consumption and usage data for charges billed by provision or actual expense.
Reading Types
| Value | Description | Used With |
|---|---|---|
MeterReading | Raw meter value at a point in time | Water, gas, electricity meters |
Consumption | Calculated consumption between two dates | Heating fuel, aggregate usage |
OccupantCount | Number of occupants at a point in time | Water, waste charges split by occupant |
EquipmentCount | Number of relevant equipment items | Heating charges split by radiator count |
Reading Subtypes
| Value | Description |
|---|---|
CommonAreas | Reading for common area consumption |
Individual | Reading for individual tenant consumption |
Maintenance | Reading taken during maintenance |
LeakFix | Reading taken after a leak repair |
Anomaly Detection
The system automatically flags suspicious readings via the anomaly field, which is a nested AnomalyDetails object (or null when no anomaly is detected):
is_anomaly(boolean): whether the reading is flagged as anomalousdeviation_percentage(number, nullable): percentage deviation from averageaverage_value(number, nullable): historical average value for comparisonthreshold_high(number, nullable): upper threshold (150% of average)threshold_low(number, nullable): lower threshold (50% of average)
Endpoints
List Readings
GET /api/charges/readings
Query Parameters:
lease_id(optional): Filter by leasecategory_id(optional): Filter by categorystart_date/end_date(optional): Date range
Response: 200 OK
Code
Create Reading
POST /api/charges/readings
Request Body:
Code
Response: 201 Created
Get Reading
GET /api/charges/readings/{id}
Response: 200 OK
Update Reading
PUT /api/charges/readings/{id}
Response: 200 OK
Delete Reading
DELETE /api/charges/readings/{id}
Response: 204 No Content
Validate Reading
GET /api/charges/readings/{id}/validate
Validates a reading against business rules (value within expected range, no duplicates for the same period, anomaly detection).
Response: 200 OK
Code
Lease Meters
Associate physical meters with leases to track consumption over time. Meters are the foundation for metered billing (RELEVE_DIRECT).
Endpoints
List Lease Meters
GET /api/leases/{lease_id}/meters
Response: 200 OK — Array of LeaseMeter
Create Lease Meter
POST /api/leases/{lease_id}/meters
Request Body:
Code
Validation rules:
start_datemust be <=end_date(if provided)initial_readingmust be <=final_reading(if both provided)billing_ratio: 0 < x <= 100
Response: 201 Created
Get / Update / Delete Lease Meter
- GET
/api/leases/{lease_id}/meters/{id}—200 OK - PUT
/api/leases/{lease_id}/meters/{id}—200 OK - DELETE
/api/leases/{lease_id}/meters/{id}—204 No Content
LeaseMeter Model
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
lease_id | UUID | Parent lease |
meter_id | UUID | Physical meter reference |
start_date | date | When the meter became active for this lease |
end_date | date? | When the meter was deactivated (null = active) |
initial_reading | decimal? | Meter reading at start |
final_reading | decimal? | Meter reading at end |
reading_frequency | enum? | DAILY, WEEKLY, MONTHLY, QUARTERLY, ANNUALLY |
is_billing_meter | boolean | Whether used for billing (default: true) |
billing_ratio | decimal? | Billing ratio % (0 < x <= 100) |
Charge Meters
Link a meter to a specific charge to define how consumption is calculated and allocated for billing.
Endpoints
List Charge Meters
GET /api/leases/{lease_id}/charges/{charge_id}/meters
Response: 200 OK — Array of LeaseChargeMeter
Create Charge Meter
POST /api/leases/{lease_id}/charges/{charge_id}/meters
Request Body:
Code
Response: 201 Created
Get / Update / Delete Charge Meter
- GET
/api/leases/{lease_id}/charges/{charge_id}/meters/{id}—200 OK - PUT
/api/leases/{lease_id}/charges/{charge_id}/meters/{id}—200 OK - DELETE
/api/leases/{lease_id}/charges/{charge_id}/meters/{id}—204 No Content
Calculation Methods
| Method | Description |
|---|---|
DIRECT | Direct consumption billing — the full metered value is billed |
WEIGHTED | Weighted by a coefficient/ratio |
SHARED | Shared proportionally among tenants |
FIXED_ALLOCATION | Fixed allocation regardless of actual consumption |
Charge Notifications
Send and track charge-related notifications to tenants and managers.
Notification Types
| Type | Description |
|---|---|
CONSUMPTION_ALERT | Alert about unusual consumption patterns |
ANNUAL_REVIEW | Annual charge review notification |
REGULARIZATION_DUE | Regularization is due for the period |
DOCUMENTATION_REQUEST | Request for supporting documents |
Notification Status Flow
Code
Endpoints
- GET
/api/leases/{lease_id}/charges/notifications— List notifications - POST
/api/leases/{lease_id}/charges/notifications— Create notification - GET
/api/leases/{lease_id}/charges/notifications/{id}— Get notification - PUT
/api/leases/{lease_id}/charges/notifications/{id}— Update notification (status, sent_date) - DELETE
/api/leases/{lease_id}/charges/notifications/{id}— Delete notification
Create Notification
Code
Charge Regulations
Apply regulatory adjustments to charges when freeze periods or legal exceptions are active.
Regulation Types
| Type | Description | Required Field |
|---|---|---|
FREEZE | Adjustment due to an active freeze period | freeze_period_id |
LEGAL_EXCEPTION | Adjustment due to a legal exception | legal_exception_id |
Business Rules
adjusted_amountcannot exceedoriginal_amount- If
regulation_type = FREEZE,freeze_period_idis required - If
regulation_type = LEGAL_EXCEPTION,legal_exception_idis required
Endpoints
- GET
/api/leases/{lease_id}/charges/{charge_id}/regulations— List regulations - POST
/api/leases/{lease_id}/charges/{charge_id}/regulations— Create regulation - GET
/api/leases/{lease_id}/charges/{charge_id}/regulations/{id}— Get regulation - PUT
/api/leases/{lease_id}/charges/{charge_id}/regulations/{id}— Update (adjusted_amount, adjustment_details) - DELETE
/api/leases/{lease_id}/charges/{charge_id}/regulations/{id}— Delete regulation
Create Regulation
Code
Charge Review Details
Each review contains detail lines comparing provisional vs. actual amounts per charge.
Review Detail Status
| Status | Description |
|---|---|
DRAFT | Detail created, not yet calculated |
CALCULATED | Amounts computed |
VALIDATED | Amounts confirmed |
DISPUTED | Tenant disputes this line |
ADJUSTED | Amount adjusted after dispute |
CLOSED | Detail finalized |
Endpoints
- GET
/api/leases/{lease_id}/charges/reviews/{review_id}/details— List details - POST
/api/leases/{lease_id}/charges/reviews/{review_id}/details— Create detail - GET
/api/leases/{lease_id}/charges/reviews/{review_id}/details/{id}— Get detail - PUT
/api/leases/{lease_id}/charges/reviews/{review_id}/details/{id}— Update detail - DELETE
/api/leases/{lease_id}/charges/reviews/{review_id}/details/{id}— Delete detail
Create Review Detail
Code
Charge Review Endpoints
Endpoints
- GET
/api/leases/{lease_id}/charges/reviews— List reviews - POST
/api/leases/{lease_id}/charges/reviews— Create review - GET
/api/leases/{lease_id}/charges/reviews/{id}— Get review - PUT
/api/leases/{lease_id}/charges/reviews/{id}— Update review - POST
/api/leases/{lease_id}/charges/reviews/{id}/transition— Transition review status - DELETE
/api/leases/{lease_id}/charges/reviews/{id}— Delete review
Transition Status
Code
Bulk Finalization
Perform bulk regularization for all charges at lease end in a single atomic transaction.
POST /api/leases/{lease_id}/charges/finalize
Code
This operation:
- Creates a single
ChargeReviewfor the lease - Creates a
ChargeReviewDetailfor each charge - Updates each charge's amount to the actual value
- All within a single database transaction (atomicity guaranteed)
Response: 200 OK — Array of updated LeaseCharge
Legal Documents (Art. 23 al. 4)
Supporting documents (justificatifs de charges) that back up charge amounts during annual regularization. Per Art. 23 al. 4 of Loi 89-462, these must be available to the tenant for 6 months after the regularization notice.
Endpoints
- GET
/api/leases/{lease_id}/charges/documents— List documents - POST
/api/leases/{lease_id}/charges/documents— Upload document - GET
/api/leases/{lease_id}/charges/documents/{id}— Get document - PUT
/api/leases/{lease_id}/charges/documents/{id}— Update document - DELETE
/api/leases/{lease_id}/charges/documents/{id}— Delete document
Audit Log
Full traceability of all modifications to lease charges. Each change records the previous values, new values, who made the change, and why.
Endpoint
GET /api/leases/{lease_id}/charges/{charge_id}/audit-log
Response: 200 OK
Code
Audit Actions
| Action | Description |
|---|---|
CREATE | Charge was created |
UPDATE | Charge was modified |
DELETE | Charge was deleted |
Distribution References
Historical reference values for distribution keys, used to compute charge allocations for a specific estate.
Global Endpoints
- GET
/api/charges/distribution-references?distribution_key_id=<uuid>— List by distribution key - GET
/api/charges/distribution-references?estate_id=<uuid>— List by estate - POST
/api/charges/distribution-references— Create reference - GET
/api/charges/distribution-references/{id}— Get reference - PUT
/api/charges/distribution-references/{id}— Update reference - DELETE
/api/charges/distribution-references/{id}— Delete reference
Create Distribution Reference
Code
Business Validation Rules
The charge system enforces multiple layers of validation:
1. Lease Status Check
- Charges cannot be modified if the lease is
TERMINATEDorEXPIRED - Allowed statuses:
DRAFT,ACTIVE,NOTICE
2. Period Overlap Detection
- New charges cannot overlap with existing charges for the same service/category
- 4 overlap types detected: new start in existing, new end in existing, new encompasses existing, existing encompasses new
3. Freeze Period Enforcement
- Active freeze periods block charge modifications for the affected category + legislative zone
- A freeze is active when:
start_date <= todayAND (end_date IS NULLORend_date >= today)
4. Amount Change Validation
- Delegates to
LeaseCharge::update_amount()for internal invariants - Skipped for creation and zero-amount charges
5. Charge-to-Rent Ratio Warning
Non-blocking warning when charges exceed:
- 40% of rent for residential leases (HABITATION_VIDE, MEUBLE)
- 50% of rent for commercial leases
Error Responses
| Status | Condition |
|---|---|
400 Bad Request | Invalid billing mode × calculation basis combination; EMPLOYEE ↔ PERSONNEL_* coupling violation; missing required fields; period overlap |
403 Forbidden | Insufficient permissions |
404 Not Found | Charge, category, or reading not found |
409 Conflict | Cannot delete category — referenced by active charges; active freeze period blocks modification |
422 Unprocessable Entity | Lease type does not allow the requested billing mode; lease is terminated/expired; service place not compatible with lease |
Notes
- All monetary values are stored as BigDecimal for precision
- Notification thresholds help identify unusual consumption patterns
- The system enforces Décret n°87-713 recovery rates automatically during settlement
- Employee charges (
EMPLOYEEcategory) are automatically capped at 75%, 40%, or 100% during régularisation depending on thePERSONNEL_*basis - Charge-to-rent ratio warnings (40% / 50%) are non-blocking business safeguards, not legal requirements
Related
- Rent Receipts — Generate rent receipts (quittances) with itemized charges
- Place Services — Link chargeable services to places
- Distribution Keys — Define how costs are split among tenants
- Lease Types — Lease type rules and constraints
- Rent Regulation — Rent control and compliance