# Place Services API

Link chargeable building services to places — elevators, heating systems, water supply, telecom infrastructure, and more. Place services define *what* is available at a property; [charges](/leases/charges) define *how* tenants pay for them.

## Quick Example

```bash
curl -X POST https://api.faireplace.com/api/places/<place_id>/services \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Chauffage collectif",
    "description": "Chauffage central au gaz naturel",
    "is_chargeable": true,
    "category_id": "<charge_category_uuid>",
    "space_type": "INDOOR_COMMON",
    "default_distribution_key_id": "<distribution_key_uuid>"
  }'
```

---

## ServicePlace Model

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | UUID | auto | Unique identifier |
| `place_id` | UUID | yes | The place this service belongs to |
| `name` | string | yes | Human-readable service name |
| `description` | string | no | Detailed description |
| `is_chargeable` | boolean | yes | Whether this service generates charges billed to tenants |
| `category_id` | UUID | conditional | Charge category (required when `is_chargeable = true`) |
| `space_type` | SpaceType | yes | Where the service operates — see enum below |
| `default_distribution_key_id` | UUID | conditional | Default cost-splitting method (required when `is_chargeable = true`) |
| `created_at` | datetime | auto | Creation timestamp |
| `updated_at` | datetime | auto | Last update timestamp |

### Business Rules

- If `is_chargeable = true`, both `category_id` and `default_distribution_key_id` are **mandatory**. The API returns `400 Bad Request` if either is missing.
- If `is_chargeable = false`, `category_id` and `default_distribution_key_id` are ignored even if provided.
- A place can have multiple services of the same `space_type`.

---

## SpaceType Enum

| Value | Description | Example Services |
|-------|-------------|------------------|
| `INDOOR_COMMON` | Indoor shared areas | Heating, lighting of hallways, staircase cleaning |
| `OUTDOOR_COMMON` | Outdoor shared areas | Garden maintenance, parking lot lighting |
| `PRIVATE` | Tenant-specific services | Individual water meter, private heating |
| `TECHNICAL` | Technical infrastructure | Elevator maintenance, boiler room |
| `GARDEN` | Green spaces | Landscaping, irrigation |
| `PARKING` | Parking facilities | Garage door, parking lighting |
| `TELECOM_SERVICES` | Telecommunications | Fiber optic, intercom, collective antenna |

---

## Endpoints

### List Services for a Place

**GET** `/api/places/{place_id}/services`

Returns all services linked to a place.

**Path Parameters:**
- `place_id` (UUID): The place ID

**Response:** `200 OK`
```json
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "place_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Ascenseur",
    "description": "Ascenseur principal, capacité 8 personnes",
    "is_chargeable": true,
    "category_id": "660e8400-e29b-41d4-a716-446655440001",
    "space_type": "TECHNICAL",
    "default_distribution_key_id": "770e8400-e29b-41d4-a716-446655440002",
    "created_at": "2024-03-01T10:00:00Z",
    "updated_at": "2024-03-01T10:00:00Z"
  },
  {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "place_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Jardin collectif",
    "description": "Entretien des espaces verts",
    "is_chargeable": true,
    "category_id": "660e8400-e29b-41d4-a716-446655440003",
    "space_type": "GARDEN",
    "default_distribution_key_id": "770e8400-e29b-41d4-a716-446655440004",
    "created_at": "2024-03-01T10:00:00Z",
    "updated_at": "2024-03-01T10:00:00Z"
  }
]
```

### Add a Service to a Place

**POST** `/api/places/{place_id}/services`

**Path Parameters:**
- `place_id` (UUID): The place ID

**Request Body:**
```json
{
  "name": "Eau froide collective",
  "description": "Compteur général eau froide",
  "is_chargeable": true,
  "category_id": "660e8400-e29b-41d4-a716-446655440005",
  "space_type": "INDOOR_COMMON",
  "default_distribution_key_id": "770e8400-e29b-41d4-a716-446655440006"
}
```

**Response:** `201 Created`
Returns the created service object.

### Remove a Service from a Place

**DELETE** `/api/places/{place_id}/services/{service_id}`

Removes a service from a place. Fails with `409 Conflict` if the service is referenced by active lease charges.

**Path Parameters:**
- `place_id` (UUID): The place ID
- `service_id` (UUID): The service ID

**Response:** `204 No Content`

---

## Error Responses

| Status | Condition |
|--------|-----------|
| `400 Bad Request` | `is_chargeable = true` but `default_distribution_key_id` or `category_id` is missing |
| `404 Not Found` | Place or service not found |
| `409 Conflict` | Cannot delete — service is referenced by active lease charges |

---

## Common Workflows

### Set up building services after creating a place

1. Create the place (`POST /api/places`)
2. Create or select [distribution keys](/leases/distribution-keys) for cost splitting
3. Add services to the place (`POST /api/places/{id}/services`)
4. When creating a lease, link services to [lease charges](/leases/charges)

### Non-chargeable services

Some services exist for documentation but are not billed to tenants (e.g., a security camera system maintained by the owner). Set `is_chargeable = false` — no category or distribution key is needed.

---

## Related

- **[Distribution Keys](/leases/distribution-keys)** — Define how shared costs are split among tenants
- **[Charges](/leases/charges)** — Billing modes, calculation bases, and lease charge management
- **[Places API](/properties/places)** — Full endpoint reference for places
- **[Property Overview](/properties/overview)** — Property hierarchy and structure
