# Lessees API

Manage tenants (locataires), corporate lessees, and guarantors (garants). Lessees are the people or companies that sign leases. Each lessee includes identity, employment, income, and banking information needed for French rental agreements.

## Quick Example

```bash
curl -X POST https://api.faireplace.com/api/lessees \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "category": "individual",
    "title": "Ms.",
    "first_name": "Marie",
    "last_name": "Martin",
    "email": "marie.martin@email.com",
    "mobile_phone": "+33698765432",
    "profession": "Ingenieure informatique",
    "monthly_income": 3800.00
  }'
```

## Common Workflows

### Add a tenant to a lease
1. `POST /api/lessees` — Create the tenant record
2. `POST /api/leases/{id}/lessees` — Associate with the lease ([Leases API](/leases/leases))

### Add a guarantor (garant)
1. `POST /api/lessees` — Create with `category: "guarantor"`
2. Include income and employer details for financial verification
3. `POST /api/leases/{id}/lessees` — Link to lease with `role: "Guarantor"`

### Bulk import tenants
1. `POST /api/lessees/bulk` — Create multiple tenants in one request

---

## Overview

The Lessees API provides comprehensive tenant management with support for:
- **Individual Tenants**: Personal information, employment, and financial data
- **Corporate Tenants**: Company information and legal entity details
- **Guarantors**: Guarantor information for lease security
- **Financial Tracking**: Income verification and banking information
- **Identity Management**: Document storage and verification
- **Custom Fields**: Flexible additional data storage
- **Authentication Integration**: Link with Better Auth system

## Authentication

All endpoints require authentication with the following permissions:
- **LesseeRead**: For GET operations
- **LesseeWrite**: For POST and PUT operations  
- **LesseeDelete**: For DELETE operations

## Base URL

All lessee endpoints are prefixed with `/api/lessees`

---

## Core Lessee Operations

### List Lessees
**GET** `/api/lessees`

Retrieve all lessees for the tenant.

**Response:**
```json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "category": "individual",
    "title": "Mr.",
    "first_name": "Jean",
    "last_name": "Dupont",
    "legal_name": null,
    "birth_date": "1985-06-15",
    "birth_place": "Paris, France",
    "email": "jean.dupont@example.com",
    "mobile_phone": "+33612345678",
    "landline_phone": "+33123456789",
    "address_street": "123 Rue de la Paix",
    "address_postal_code": "75001",
    "address_city": "Paris",
    "address_country": "France",
    "profession": "Software Engineer",
    "employer_name": "Tech Solutions SA",
    "employer_phone": "+33145678901",
    "monthly_income": 4500.00,
    "other_income": 500.00,
    "bank_name": "Crédit Agricole",
    "iban": "FR1420041010050500013M02606",
    "bic": "AGRIFRPP",
    "additional_addresses": null,
    "identity_documents": {
      "passport": {
        "number": "123456789",
        "expiry": "2029-06-15"
      }
    },
    "additional_contacts": null,
    "custom_fields": {
      "emergency_contact": "Marie Dupont - 0987654321"
    },
    "auth_user_id": "auth_user_123",
    "created_at": "2024-01-15T10:30:00",
    "updated_at": "2024-01-15T10:30:00"
  }
]
```

### Create Lessee
**POST** `/api/lessees`

Create a new lessee (tenant).

**Request Body:**
```json
{
  "category": "individual",
  "title": "Ms.",
  "first_name": "Marie",
  "last_name": "Martin",
  "birth_date": "1990-03-20",
  "birth_place": "Lyon, France",
  "email": "marie.martin@example.com",
  "mobile_phone": "+33698765432",
  "landline_phone": "+33187654321",
  "address_street": "456 Avenue des Champs",
  "address_postal_code": "69001",
  "address_city": "Lyon",
  "address_country": "France",
  "profession": "Marketing Manager",
  "employer_name": "Creative Agency",
  "employer_phone": "+33478901234",
  "monthly_income": 3800.00,
  "other_income": 200.00,
  "bank_name": "BNP Paribas",
  "iban": "FR1430002005500000157841Z25",
  "bic": "BNPAFRPP",
  "identity_documents": {
    "id_card": {
      "number": "987654321",
      "expiry": "2028-03-20"
    }
  },
  "custom_fields": {
    "preferred_language": "French",
    "pet_owner": true
  }
}
```

**Response:** `201 Created`
Returns the created lessee object with generated ID and timestamps.

### Get Lessee
**GET** `/api/lessees/{id}`

Retrieve a specific lessee by ID.

**Path Parameters:**
- `id` (UUID): The lessee ID

**Response:** `200 OK`
Returns the lessee object.

### Update Lessee
**PUT** `/api/lessees/{id}`

Update an existing lessee. All fields are optional in update requests.

**Path Parameters:**
- `id` (UUID): The lessee ID

**Request Body:**
```json
{
  "email": "marie.martin.updated@example.com",
  "mobile_phone": "+33612345678",
  "monthly_income": 4000.00,
  "profession": "Senior Marketing Manager"
}
```

**Response:** `200 OK`
Returns the updated lessee object.

### Delete Lessee
**DELETE** `/api/lessees/{id}`

Delete a lessee (only possible if not associated with active leases).

**Path Parameters:**
- `id` (UUID): The lessee ID

**Response:** `204 No Content`

---

## Category-Based Operations

### Get Lessees by Category
**GET** `/api/lessees/type/{type}`

Retrieve lessees by their category type.

**Path Parameters:**
- `type` (string): The lessee category (`individual`, `company/other`, `guarantor`)

**Response:** `200 OK`
Returns array of lessees matching the specified category.

**Example Response:**
```json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440010",
    "category": "guarantor",
    "title": "Mr.",
    "first_name": "Pierre",
    "last_name": "Guarantor",
    "email": "pierre.guarantor@example.com",
    "mobile_phone": "+33612345679",
    "monthly_income": 6000.00,
    "profession": "Bank Manager",
    "employer_name": "Major Bank SA",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
]
```

---

## Bulk Operations

### Create Multiple Lessees
**POST** `/api/lessees/bulk`

Create multiple lessees in a single request.

**Request Body:**
```json
[
  {
    "category": "individual",
    "first_name": "Sophie",
    "last_name": "Leroy",
    "email": "sophie.leroy@email.com",
    "mobile_phone": "+33612345680",
    "monthly_income": 3200.00,
    "profession": "Enseignante"
  },
  {
    "category": "individual",
    "first_name": "Lucas",
    "last_name": "Moreau",
    "email": "lucas.moreau@email.com",
    "mobile_phone": "+33612345681",
    "monthly_income": 3500.00,
    "profession": "Infirmier"
  }
]
```

**Response:** `201 Created`
Returns array of created lessee objects.

### Delete Multiple Lessees
**DELETE** `/api/lessees/bulk`

Delete multiple lessees by their IDs.

**Request Body:**
```json
[
  "550e8400-e29b-41d4-a716-446655440000",
  "550e8400-e29b-41d4-a716-446655440001"
]
```

**Response:** `204 No Content`

---

## Data Types and Structures

### Lessee Categories
- `individual` - Individual person tenant
- `company/other` - Corporate or other entity tenant  
- `guarantor` - Guarantor for lease security

### Individual Lessee Fields
```json
{
  "category": "individual",              // Required
  "title": "Mr./Ms./Dr.",               // Optional
  "first_name": "string",               // Required for individuals
  "last_name": "string",                // Required for individuals
  "legal_name": null,                   // Not used for individuals
  "birth_date": "YYYY-MM-DD",           // Optional
  "birth_place": "string",              // Optional
  "email": "email@example.com",         // Required, must be valid email
  "mobile_phone": "+33612345678",       // Optional
  "landline_phone": "+33123456789",     // Optional
  "address_street": "string",           // Optional
  "address_postal_code": "string",      // Optional
  "address_city": "string",             // Optional
  "address_country": "string",          // Optional
  "profession": "string",               // Optional
  "employer_name": "string",            // Optional
  "employer_phone": "string",           // Optional
  "monthly_income": "BigDecimal",       // Optional
  "other_income": "BigDecimal",         // Optional
  "bank_name": "string",                // Optional
  "iban": "string",                     // Optional, 15-34 characters
  "bic": "string",                      // Optional, 8 or 11 characters
  "additional_addresses": "JSON",       // Optional
  "identity_documents": "JSON",         // Optional
  "additional_contacts": "JSON",        // Optional
  "custom_fields": "JSON",              // Optional
  "auth_user_id": "string"              // Optional
}
```

### Company Lessee Fields
```json
{
  "category": "company/other",          // Required
  "title": null,                        // Not used for companies
  "first_name": "Contact Name",         // Optional
  "last_name": "Contact Surname",       // Optional  
  "legal_name": "Company Legal Name",   // Required for companies
  "birth_date": null,                   // Not used for companies
  "birth_place": null,                  // Not used for companies
  "email": "contact@company.com",       // Required
  "mobile_phone": "+33612345678",       // Optional
  "address_street": "Business Address", // Optional
  "profession": "Industry Type",        // Optional
  "employer_name": null,                // Not applicable
  "monthly_income": "Company Revenue",  // Optional
  "custom_fields": {                    // Optional
    "registration_number": "SIRET123456789",
    "vat_number": "FR12345678901"
  }
}
```

### Guarantor Fields
```json
{
  "category": "guarantor",              // Required
  "first_name": "string",               // Required if no legal_name
  "last_name": "string",                // Required if no legal_name
  "legal_name": "string",               // Required if guarantor is company
  "email": "guarantor@example.com",     // Required
  "monthly_income": "BigDecimal",       // Important for guarantors
  "profession": "string",               // Optional
  "employer_name": "string",            // Optional
  "bank_name": "string",                // Optional
  "iban": "string",                     // Optional
  "identity_documents": "JSON",         // Optional
  "custom_fields": {                    // Optional
    "guarantee_amount": 5000.00,
    "guarantee_type": "solidarity"
  }
}
```

### Identity Documents Structure
```json
{
  "passport": {
    "number": "123456789",
    "expiry": "2029-06-15",
    "issuing_country": "France"
  },
  "id_card": {
    "number": "987654321",
    "expiry": "2028-03-20",
    "issuing_authority": "Prefecture de Paris"
  },
  "driving_license": {
    "number": "DL123456789",
    "expiry": "2026-12-31"
  }
}
```

### Additional Addresses Structure
```json
{
  "work_address": {
    "street": "789 Business Avenue",
    "postal_code": "75008",
    "city": "Paris",
    "country": "France"
  },
  "previous_address": {
    "street": "321 Old Street",
    "postal_code": "69002",
    "city": "Lyon",
    "country": "France"
  }
}
```

### Additional Contacts Structure
```json
{
  "emergency_contact": {
    "name": "Emergency Person",
    "phone": "+33612345678",
    "relationship": "Family"
  },
  "references": [
    {
      "name": "Previous Landlord",
      "phone": "+33123456789",
      "type": "landlord"
    }
  ]
}
```

---

## Validation Rules

### Required Fields by Category
- **Individual**: `category`, `first_name`, `last_name`, `email`
- **Company**: `category`, `legal_name`, `email`
- **Guarantor**: `category`, `email`, and either (`first_name` + `last_name`) or `legal_name`

### Field Validation
- **Email**: Must contain '@' and '.' characters
- **IBAN**: Must be 15-34 characters long
- **BIC**: Must be 8 or 11 characters long  
- **Phone**: Should follow international format
- **Names**: Cannot be empty strings

---

## Error Responses

### Validation Errors
**400 Bad Request**
```json
{
  "error": "ValidationError",
  "message": "Invalid lessee data",
  "details": [
    {
      "field": "first_name",
      "message": "First name is required for individual lessees"
    },
    {
      "field": "email",
      "message": "Invalid email format"
    }
  ]
}
```

### Category Validation Error
```json
{
  "error": "ValidationError",
  "message": "Invalid lessee category",
  "details": [
    {
      "field": "category",
      "message": "Category must be one of: individual, company/other, guarantor"
    }
  ]
}
```

### Not Found
**404 Not Found**
```json
{
  "error": "NotFound",
  "message": "Lessee {id} not found"
}
```

### Conflict
**409 Conflict**
```json
{
  "error": "Conflict",
  "message": "Cannot delete lessee with active leases"
}
```

---

## Common Use Cases

### Creating an Individual Tenant
1. Create lessee with `POST /api/lessees`
2. Set `category` to "individual"
3. Provide required personal information
4. Include employment and income details for verification
5. Add banking information for rent payments

### Managing Corporate Tenants
1. Create lessee with `category` set to "company/other"
2. Provide `legal_name` instead of individual names
3. Include contact person information
4. Add company registration details in `custom_fields`

### Adding Guarantors
1. Create lessee with `category` set to "guarantor"
2. Provide either individual or company information
3. Include financial information for guarantee assessment
4. Link to main tenant through lease relationships

### Bulk Tenant Import
1. Prepare tenant data in required format
2. Use `POST /api/lessees/bulk` for batch creation
3. Handle validation errors for individual tenants
4. Process successful creations and failed validations separately

### Income Verification Workflow
1. Create tenant with basic information
2. Update with employment details using `PUT /api/lessees/{id}`
3. Add income verification documents in `identity_documents`
4. Track verification status in `custom_fields`

---

## Integration Notes

- **Lease Management**: Lessees are associated with leases through the leases API
- **Authentication**: Integration with Better Auth through `auth_user_id`
- **Document Storage**: Identity documents stored as JSON structures
- **Financial Verification**: Income data used for lease qualification
- **Communication**: Contact information used for lease notifications
- **Compliance**: Data handling follows GDPR and French data protection laws

---

## Business Rules

- **Email Uniqueness**: Each lessee must have a unique email address
- **Category Consistency**: Fields must be appropriate for the selected category
- **Active Lease Protection**: Cannot delete lessees with active leases
- **Income Verification**: Monthly income should be at least 3x rent amount (business rule)
- **Guarantor Requirements**: Guarantors should have higher income than primary tenants
- **Data Retention**: Personal data retained according to legal requirements
- **Authentication Linking**: `auth_user_id` enables tenant self-service portal access