FairePlace Lease Notices API
Notice periods and congés (notice given by either party).
Notice periods and congés (notice given by either party).
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/faireplace-com:faireplace-com-lease-notices-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: FairePlace Property Management Lease Notices API
description: 'Comprehensive API for managing properties, leases, tenants, and all aspects of real estate management.
Built with Rust and Actix-web following hexagonal architecture principles.
## Authentication
This API uses API keys for authentication with tenant-based isolation.
## Base URL
- Production: `https://api.faireplace.com/api`'
version: 1.0.0
contact:
name: FairePlace API Support
email: api-support@faireplace.com
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.faireplace.com/api
description: Production server
security:
- BearerAuth: []
tags:
- name: Lease Notices
description: Notice periods and congés (notice given by either party).
paths:
/leases/{lease_id}/notices:
post:
operationId: createLeaseNotice
summary: Create a lease notice
description: 'Create a lease notice (congé) for a lease: landlord or tenant side.
**French law context (art. 15 loi 89-462, loi ALUR):**
A notice terminates or non-renews the lease. The system automatically computes:
- `notice_period_months` based on type/reason/lease type
- `effective_date` = notice_date + period (last day of month)
- `tenant_preemption_expires_at` for sale notices (2 months)
Created with `DRAFT` status. Use `POST /leases/{lease_id}/notices/{notice_id}/generate-letter` → `PUT /leases/{lease_id}/notices/{notice_id}/send` → `PUT /leases/{lease_id}/notices/{notice_id}/receive` workflow.
**Permissions required:** `leases:write`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- notice_type
- notice_reason
- initiated_by
- notice_date
properties:
notice_type:
type: string
enum:
- LANDLORD_NOTICE
- TENANT_NOTICE
notice_reason:
type: string
enum:
- SALE
- PERSONAL_USE
- LEGITIMATE_SERIOUS
- TENANT_STANDARD
- TENSE_ZONE
- FIRST_EMPLOYMENT
- PROFESSIONAL_TRANSFER
- JOB_LOSS
- NEW_JOB_AFTER_JOB_LOSS
- RSA_BENEFICIARY
- AAH_BENEFICIARY
- HEALTH_CONDITION
- DOMESTIC_VIOLENCE
- SOCIAL_HOUSING_ATTRIBUTION
- MUTUAL_AGREEMENT
initiated_by:
type: string
format: uuid
description: Person ID (owner or lessee) who initiates the notice
notice_date:
type: string
format: date
delivery_method:
type:
- string
- 'null'
enum:
- LRAR
- HUISSIER
- HAND_DELIVERY
- ELECTRONIC_LRAR
- null
sale_price:
type:
- number
- 'null'
format: decimal
description: Sale price (landlord sale notice only)
sale_conditions:
type:
- string
- 'null'
beneficiary_name:
type:
- string
- 'null'
description: Name of the person for personal use (landlord reprise only)
beneficiary_address:
type:
- string
- 'null'
beneficiary_relationship:
type:
- string
- 'null'
enum:
- SELF
- SPOUSE
- PACS_PARTNER
- COHABITANT
- ASCENDANT
- DESCENDANT
- null
reprise_justification:
type:
- string
- 'null'
legitimate_reason_detail:
type:
- string
- 'null'
reduced_notice_justification:
type:
- string
- 'null'
description: Justification for reduced notice period (tenant only)
notes:
type:
- string
- 'null'
responses:
'201':
description: Notice created
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
get:
operationId: listLeaseNotices
summary: List lease notices
description: 'List all notices for a lease, with optional status filter.
**Permissions required:** `leases:read`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: status
in: query
required: false
schema:
type: string
enum:
- DRAFT
- SENT
- RECEIVED
- ACKNOWLEDGED
- CONTESTED
- EFFECTIVE
- CANCELLED
responses:
'200':
description: List of notices
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/LeaseNoticeResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/leases/{lease_id}/notices/compute-dates:
get:
operationId: computeNoticeDates
summary: Compute notice dates
description: 'Pure computation endpoint. Calculates notice period, effective date, and preemption expiry
based on notice type, reason, and lease type.
**Permissions required:** `leases:read`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_type
in: query
required: true
schema:
type: string
enum:
- LANDLORD_NOTICE
- TENANT_NOTICE
- name: notice_reason
in: query
required: true
schema:
type: string
enum:
- SALE
- PERSONAL_USE
- LEGITIMATE_SERIOUS
- TENANT_STANDARD
- TENSE_ZONE
- FIRST_EMPLOYMENT
- PROFESSIONAL_TRANSFER
- JOB_LOSS
- NEW_JOB_AFTER_JOB_LOSS
- RSA_BENEFICIARY
- AAH_BENEFICIARY
- HEALTH_CONDITION
- DOMESTIC_VIOLENCE
- SOCIAL_HOUSING_ATTRIBUTION
- MUTUAL_AGREEMENT
- name: lease_type
in: query
required: true
schema:
type: string
description: '"VIDE" or "MEUBLE"'
- name: reception_date
in: query
required: false
schema:
type: string
format: date
description: Base date for computation (defaults to today)
responses:
'200':
description: Computed dates
content:
application/json:
schema:
type: object
properties:
notice_period_months:
type: integer
effective_date:
type: string
format: date
preemption_expires_at:
type:
- string
- 'null'
format: date
'401':
$ref: '#/components/responses/Unauthorized'
/leases/{lease_id}/notices/{notice_id}:
get:
operationId: getLeaseNotice
summary: Get a lease notice
description: 'Retrieve detailed information about a specific notice.
**Permissions required:** `leases:read`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Notice details
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'404':
description: Notice not found
put:
operationId: updateLeaseNotice
summary: Update a lease notice
description: 'Update a notice (Draft status only). If type/reason/date change, dates are recalculated.
**Permissions required:** `leases:write`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
notice_type:
type: string
enum:
- LANDLORD_NOTICE
- TENANT_NOTICE
notice_reason:
type: string
enum:
- SALE
- PERSONAL_USE
- LEGITIMATE_SERIOUS
- TENANT_STANDARD
- TENSE_ZONE
- FIRST_EMPLOYMENT
- PROFESSIONAL_TRANSFER
- JOB_LOSS
- NEW_JOB_AFTER_JOB_LOSS
- RSA_BENEFICIARY
- AAH_BENEFICIARY
- HEALTH_CONDITION
- DOMESTIC_VIOLENCE
- SOCIAL_HOUSING_ATTRIBUTION
- MUTUAL_AGREEMENT
initiated_by:
type: string
format: uuid
notice_date:
type: string
format: date
delivery_method:
type: string
enum:
- LRAR
- HUISSIER
- HAND_DELIVERY
- ELECTRONIC_LRAR
sale_price:
type: number
format: decimal
sale_conditions:
type: string
beneficiary_name:
type: string
beneficiary_address:
type: string
beneficiary_relationship:
type: string
enum:
- SELF
- SPOUSE
- PACS_PARTNER
- COHABITANT
- ASCENDANT
- DESCENDANT
reprise_justification:
type: string
legitimate_reason_detail:
type: string
reduced_notice_justification:
type: string
notes:
type: string
responses:
'200':
description: Notice updated
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'400':
description: Only draft notices can be updated
'404':
description: Notice not found
delete:
operationId: deleteLeaseNotice
summary: Delete a lease notice
description: 'Delete a notice (Draft status only).
**Permissions required:** `leases:delete`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Notice deleted
'400':
description: Only draft notices can be deleted
'404':
description: Notice not found
/leases/{lease_id}/notices/{notice_id}/generate-letter:
post:
operationId: generateNoticeLetterPDF
summary: Generate notice letter PDF
description: 'Generate the formal notice letter as a PDF using Typst templates.
Selects the appropriate template based on `notice_type` and `notice_reason`:
- Landlord → `conge_bailleur.typ` (3 variants: sale/reprise/legitimate)
- Tenant → `conge_locataire.typ` (11 variants: standard + 10 reduced)
- Mutual → `resiliation_amiable.typ`
Updates `document_url` on the notice.
**Permissions required:** `leases:write`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: PDF generated, notice updated with document_url
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'404':
description: Notice not found
/leases/{lease_id}/notices/{notice_id}/send:
put:
operationId: markNoticeAsSent
summary: Mark notice as sent
description: 'Transition notice from `DRAFT` to `SENT`. Requires `document_url` to be set
(letter must be generated first). Records delivery method and optional tracking number.
**Permissions required:** `leases:write`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- delivery_method
properties:
delivery_method:
type: string
enum:
- LRAR
- HUISSIER
- HAND_DELIVERY
- ELECTRONIC_LRAR
tracking_number:
type:
- string
- 'null'
responses:
'200':
description: Notice marked as sent
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'400':
description: Only draft notices with generated letter can be sent
/leases/{lease_id}/notices/{notice_id}/receive:
put:
operationId: markNoticeAsReceived
summary: Mark notice as received
description: 'Transition notice from `SENT` to `RECEIVED`. Records `reception_date` and recalculates:
- `effective_date` from reception_date + notice period
- `tenant_preemption_expires_at` for sale notices (reception_date + 2 months)
**Permissions required:** `leases:write`'
tags:
- Lease Notices
security:
- BearerAuth: []
parameters:
- name: lease_id
in: path
required: true
schema:
type: string
format: uuid
- name: notice_id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- reception_date
properties:
reception_date:
type: string
format: date
responses:
'200':
description: Notice marked as received with recalculated dates
content:
application/json:
schema:
$ref: '#/components/schemas/LeaseNoticeResponse'
'400':
description: Only sent notices can be marked as received
components:
responses:
Forbidden:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
LeaseNoticeResponse:
type: object
properties:
id:
type: string
format: uuid
lease_id:
type: string
format: uuid
notice_type:
type: string
enum:
- LANDLORD_NOTICE
- TENANT_NOTICE
notice_reason:
type: string
enum:
- SALE
- PERSONAL_USE
- LEGITIMATE_SERIOUS
- TENANT_STANDARD
- TENSE_ZONE
- FIRST_EMPLOYMENT
- PROFESSIONAL_TRANSFER
- JOB_LOSS
- NEW_JOB_AFTER_JOB_LOSS
- RSA_BENEFICIARY
- AAH_BENEFICIARY
- HEALTH_CONDITION
- DOMESTIC_VIOLENCE
- SOCIAL_HOUSING_ATTRIBUTION
- MUTUAL_AGREEMENT
initiated_by:
type: string
format: uuid
notice_date:
type: string
format: date
reception_date:
type:
- string
- 'null'
format: date
effective_date:
type: string
format: date
notice_period_months:
type: integer
delivery_method:
type:
- string
- 'null'
enum:
- LRAR
- HUISSIER
- HAND_DELIVERY
- ELECTRONIC_LRAR
- null
tracking_number:
type:
- string
- 'null'
status:
type: string
enum:
- DRAFT
- SENT
- RECEIVED
- ACKNOWLEDGED
- CONTESTED
- EFFECTIVE
- CANCELLED
document_url:
type:
- string
- 'null'
signed_document_url:
type:
- string
- 'null'
sale_price:
type:
- number
- 'null'
format: decimal
sale_conditions:
type:
- string
- 'null'
beneficiary_name:
type:
- string
- 'null'
beneficiary_address:
type:
- string
- 'null'
beneficiary_relationship:
type:
- string
- 'null'
enum:
- SELF
- SPOUSE
- PACS_PARTNER
- COHABITANT
- ASCENDANT
- DESCENDANT
- null
reprise_justification:
type:
- string
- 'null'
legitimate_reason_detail:
type:
- string
- 'null'
tenant_preemption_expires_at:
type:
- string
- 'null'
format: date
tenant_preemption_response:
type:
- string
- 'null'
enum:
- ACCEPTED
- DECLINED
- EXPIRED
- null
reduced_notice_justification:
type:
- string
- 'null'
justification_document_url:
type:
- string
- 'null'
tenant_age_at_notice:
type:
- integer
- 'null'
tenant_income_eligible:
type:
- boolean
- 'null'
landlord_age_exemption:
type:
- boolean
- 'null'
rehousing_offer:
type:
- string
- 'null'
contestation_reason:
type:
- string
- 'null'
notes:
type:
- string
- 'null'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
Error:
type: object
description: "The error envelope returned by every authenticated endpoint.\n\nTwo things are worth knowing before you write your error handling:\n\n- **`code` is a symbolic string, not a number.** The numeric HTTP status is\n in `status`. Branch on `code`: it is stable, and show `message`, which\n is written for humans and may be reworded without notice.\n- The public guest-signature endpoints use a **different, flatter shape**\n (`{ \"error_code\": …, \"message\": … }`, no `error` wrapper), because they\n are consumed by a page that has no session. Their responses document it\n inline.\n\nThe `X-Request-Id` response header carries the request identifier: quote it\nwhen reporting a problem. It is a header, not a body field.\n"
required:
- error
properties:
error:
type: object
required:
- code
- message
- status
properties:
code:
type: string
description: Stable symbolic code. Branch on this.
enum:
- NOT_FOUND
- UNAUTHORIZED
- VALIDATION_ERROR
- DATABASE_ERROR
- BUSINESS_ERROR
- STORAGE_ERROR
- CONFIG_ERROR
- FORBIDDEN
- CONFLICT
- PARSE_ERROR
- SERIALIZATION_ERROR
- AUTHENTICATION_ERROR
- AUTHORIZATION_ERROR
- EXTERNAL_SERVICE_ERROR
- RATE_LIMIT_EXCEEDED
- PAYMENT_REQUIRED
- PLAN_LIMIT_REACHED
- GONE
- BAD_REQUEST
- INTERNAL_ERROR
- INTERNAL_SERVER_ERROR
example: NOT_FOUND
message:
type: string
description: 'Human-readable explanation, most often in French. Safe to display,
not safe to parse.
'
example: Lease not found
status:
type: integer
description: The HTTP status code, repeated in the body.
example: 404
details:
type: object
additionalProperties: true
description: 'Extra machine-readable context. Only present on some errors: on
`RATE_LIMIT_EXCEEDED` it carries `retry_after_seconds`.
'
example:
retry_after_seconds: 12
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: API key with fp_* prefix, passed as Bearer token
WorkerApiKey:
type: apiKey
in: header
name: X-API-Key
WorkerBearer:
type: http
scheme: bearer
bearerFormat: Worker