Work with this as data
Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
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.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/faireplace-com:faireplace-com-places-api"
All apis
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.
Get an API 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 Specification
openapi: 3.2.0
info:
title: FairePlace Property Management Places 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: Places
description: Building/residence management
paths:
/places:
get:
operationId: listPlaces
summary: List places
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: search
in: query
required: false
description: Free-text search over name and address (street, city, postcode, country).
schema:
type: string
- name: name
in: query
required: false
schema:
type: string
- name: address
in: query
required: false
schema:
type: string
- name: ban_id
in: query
required: false
description: 'Base Adresse Nationale key. Exact match: this is what deduplicates addresses.'
schema:
type: string
- name: city
in: query
required: false
schema:
type: string
- name: postal_code
in: query
required: false
schema:
type: string
- name: country
in: query
required: false
schema:
type: string
- name: place_type_id
in: query
required: false
schema:
type: string
format: uuid
- name: owner_id
in: query
required: false
schema:
type: string
format: uuid
- name: created_after
in: query
required: false
schema:
type: string
format: date
- name: created_before
in: query
required: false
schema:
type: string
format: date
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/SortBy'
- $ref: '#/components/parameters/SortOrder'
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Place'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createPlace
summary: Create place
tags:
- Places
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePlace'
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Place'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalServerError'
/places/{id}:
get:
operationId: getPlace
summary: Get place
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Place'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: updatePlace
summary: Update place
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdatePlace'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Place'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: deletePlace
summary: Delete place
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: No Content
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 'Conflict - The place cannot be deleted because it contains one or more estates.
This error occurs when you attempt to delete a place that contains real estate properties. Foreign key constraints prevent deletion to preserve data integrity.
**Solution**: First delete or move all estates associated with this place before deleting it.
'
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalServerError'
/places/{id}/services:
get:
operationId: listPlaceServices
summary: List place services
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/PlaceService'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: addServicePlace
summary: Add a service to a place
description: 'Attaches a service (heating, elevator, caretaker, …) to a building.
Two ways to call it:
- **omit `service_id`**: a new service is created for this place and
the identifier is generated server-side;
- **pass `service_id`**: that identifier is used as-is, which is what
you want when you mirror services that already have an id in your own
system.
A service left without a `name` is stored as `"Service par défaut"`.
**Validation**: when `is_chargeable` is `true`,
`default_distribution_key_id` is required: a chargeable service with no
distribution key could not be spread across the tenants at
regularisation time, so the call is rejected with `400` rather than
creating a service that would break the yearly charge run.'
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LinkServiceToPlace'
example:
name: Chauffage collectif
is_chargeable: true
space_type: TECHNICAL
default_distribution_key_id: 550e8400-e29b-41d4-a716-446655440000
description: Chaufferie gaz, relevé annuel
responses:
'201':
description: Service added to the place
content:
application/json:
schema:
$ref: '#/components/schemas/PlaceService'
'400':
description: 'Invalid payload: most often `is_chargeable: true` without
`default_distribution_key_id`.
'
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/places/{id}/services/{service_id}:
delete:
operationId: removeServicePlace
summary: Remove service from place
tags:
- Places
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: service_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: No Content
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
components:
responses:
Forbidden:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Conflict:
description: Conflict
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
UnprocessableEntity:
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
parameters:
Page:
name: page
in: query
required: false
description: Zero-based page index. The first page is `0`.
schema:
type: integer
minimum: 0
default: 0
SortOrder:
name: sort_order
in: query
required: false
schema:
type: string
enum:
- asc
- desc
Limit:
name: limit
in: query
required: false
description: Rows per page. Defaults to 50.
schema:
type: integer
minimum: 1
default: 50
SortBy:
name: sort_by
in: query
required: false
description: Field to sort on (`created_at`, `last_name`, `email`, …).
schema:
type: string
schemas:
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
Place:
type: object
properties:
id:
type:
- string
- 'null'
format: uuid
name:
type:
- string
- 'null'
country:
type:
- string
- 'null'
address_complement:
type:
- string
- 'null'
street_number:
type:
- string
- 'null'
street_name:
type:
- string
- 'null'
locality:
type:
- string
- 'null'
postal_code:
type:
- string
- 'null'
city:
type:
- string
- 'null'
postal_box:
type:
- string
- 'null'
latitude:
type:
- number
- 'null'
longitude:
type:
- number
- 'null'
description:
type:
- string
- 'null'
type_id:
type:
- string
- 'null'
format: uuid
country_id:
type:
- string
- 'null'
format: uuid
digicode:
type:
- string
- 'null'
number_of_floor:
type:
- integer
- 'null'
owner_id:
type:
- string
- 'null'
format: uuid
previous_owner_id:
type:
- string
- 'null'
format: uuid
construction_date:
type:
- string
- 'null'
format: date-time
renovation_date:
type:
- string
- 'null'
format: date-time
place_category:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/PlaceCategory'
legal_regime:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/PlaceLegalRegime'
created_at:
type:
- string
- 'null'
format: date-time
updated_at:
type:
- string
- 'null'
format: date-time
LinkServiceToPlace:
type: object
description: 'Data for adding a service to a place.
**Validation rules:**
- If `is_chargeable = true`, `default_distribution_key_id` is **required**
- Validation is performed before persistence
- If validation fails, an HTTP 400 error is returned with an explicit message
'
properties:
service_id:
type:
- string
- 'null'
format: uuid
description: Service ID (optional, automatically generated if not provided)
name:
type:
- string
- 'null'
description: Service name (e.g., Heating, Elevator)
is_chargeable:
type:
- boolean
- 'null'
description: 'Indicates whether the service can be billed as charges.
**If `true`, `default_distribution_key_id` becomes required.**
'
space_type:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/ServiceSpaceType'
description: Type of space concerned by the service
description:
type:
- string
- 'null'
description: Detailed service description
default_distribution_key_id:
type:
- string
- 'null'
format: uuid
description: 'Default distribution key for billing.
**Required if `is_chargeable = true`**.
Automatically used when creating a charge if `distribution_key_id` is not provided.
'
category_id:
type:
- string
- 'null'
format: uuid
description: Charge category ID if the service is billable
ServiceSpaceType:
type: string
description: Space type for place services
enum:
- INDOOR_COMMON
- OUTDOOR_COMMON
- PRIVATE
- TECHNICAL
- GARDEN
- PARKING
- TELECOM_SERVICES
example: INDOOR_COMMON
CreatePlace:
type: object
required:
- name
- type_id
- country_id
- owner_id
- country
- street_name
- postal_code
- city
- place_category
- legal_regime
properties:
name:
type: string
type_id:
type: string
format: uuid
country_id:
type: string
format: uuid
owner_id:
type: string
format: uuid
country:
type: string
address_complement:
type:
- string
- 'null'
street_number:
type:
- string
- 'null'
street_name:
type: string
locality:
type:
- string
- 'null'
postal_code:
type: string
city:
type: string
postal_box:
type:
- string
- 'null'
latitude:
type:
- number
- 'null'
longitude:
type:
- number
- 'null'
description:
type:
- string
- 'null'
digicode:
type:
- string
- 'null'
number_of_floor:
type:
- integer
- 'null'
place_category:
type: string
legal_regime:
type: string
construction_date:
type:
- string
- 'null'
format: date-time
renovation_date:
type:
- string
- 'null'
format: date-time
PlaceService:
type: object
properties:
id:
type:
- string
- 'null'
format: uuid
place_id:
type:
- string
- 'null'
format: uuid
service_id:
type:
- string
- 'null'
format: uuid
name:
type:
- string
- 'null'
description:
type:
- string
- 'null'
is_chargeable:
type:
- boolean
- 'null'
category_id:
type:
- string
- 'null'
format: uuid
space_type:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/ServiceSpaceType'
default_distribution_key_id:
type:
- string
- 'null'
format: uuid
created_at:
type:
- string
- 'null'
format: date-time
UpdatePlace:
type: object
description: 'Data for updating an existing place.
**Update behavior for optional fields**:
- **Field absent**: the existing value is preserved (no modification)
- **Field present with `null`**: the value is removed (set to NULL in the database)
- **Field present with a value**: the value is updated
**Fields affected by this behavior**:
- `address_complement`: can be set to `null` to remove the value
- `street_number`: can be set to `null` to remove the value
- `locality`: can be set to `null` to remove the value
- `postal_box`: can be set to `null` to remove the value
- `latitude`: can be set to `null` to remove the value
- `longitude`: can be set to `null` to remove the value
**Fields assigned directly (can already be set to null)**:
- `description`, `digicode`, `number_of_floor`, `renovation_date`
'
properties:
name:
type:
- string
- 'null'
country:
type:
- string
- 'null'
address_complement:
type:
- string
- 'null'
description: 'Address complement.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- String: the value is updated
'
street_number:
type:
- string
- 'null'
description: 'Street number.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- String: the value is updated
'
street_name:
type:
- string
- 'null'
locality:
type:
- string
- 'null'
description: 'Locality.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- String: the value is updated
'
postal_code:
type:
- string
- 'null'
city:
type:
- string
- 'null'
postal_box:
type:
- string
- 'null'
description: 'Postal box.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- String: the value is updated
'
latitude:
type:
- number
- 'null'
description: 'GPS latitude.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- Number: the value is updated
'
longitude:
type:
- number
- 'null'
description: 'GPS longitude.
**Update behavior**:
- Field absent: the existing value is preserved
- `null`: the value is removed (set to NULL in the database)
- Number: the value is updated
'
description:
type:
- string
- 'null'
type_id:
type:
- string
- 'null'
format: uuid
country_id:
type:
- string
- 'null'
format: uuid
digicode:
type:
- string
- 'null'
number_of_floor:
type:
- integer
- 'null'
place_category:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/PlaceCategory'
legal_regime:
type:
- string
- 'null'
allOf:
- $ref: '#/components/schemas/PlaceLegalRegime'
renovation_date:
type:
- string
- 'null'
format: date-time
PlaceLegalRegime:
type: string
description: Legal regime of the place
enum:
- MonoPropriete
- Copropriete
example: Copropriete
PlaceCategory:
type: string
description: Place category (individual or collective)
enum:
- Individual
- Collective
example: Collective
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