FairePlace Mandates API
Management mandates (mandats de gestion) between a principal (owner/lessee) and a mandataire: create, attach a document, activate, and revoke.
Management mandates (mandats de gestion) between a principal (owner/lessee) and a mandataire: create, attach a document, activate, and revoke.
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-mandates-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 Mandates 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: Mandates
description: 'Management mandates (mandats de gestion) between a principal (owner/lessee)
and a mandataire: create, attach a document, activate, and revoke.'
paths:
/mandates:
get:
operationId: listMandates
summary: List mandates
description: 'Lists the mandates visible to the authenticated user, filtered by their role.
## Role filter
The `role` query parameter controls which mandates are returned:
- `mandataire` (default): mandates where the user is the **delegate**
- `principal`: mandates where the user is the **principal** (the person who granted the mandate)
An empty or missing `role` is treated as `mandataire`. Any other value returns `400`.
## Multi-tenant isolation
Mandates are automatically scoped to the `tenant_id` extracted from the JWT.
## Usage Example
```bash
curl -X GET "https://api.faireplace.com/api/mandates?role=mandataire" \
-H "Authorization: Bearer YOUR_API_KEY"
```
**Response**:
```json
[
{
"id": "770e8400-e29b-41d4-a716-446655440222",
"tenant_id": "tenant_123",
"mandataire_auth_user_id": "user_456",
"principal": {
"person_id": "550e8400-e29b-41d4-a716-446655440000",
"kind": "owner",
"display_name": "Jean Dupont"
},
"scope": ["initiate_signature", "sign_on_behalf"],
"valid_from": "2026-01-01",
"valid_until": "2026-12-31",
"mandate_document": { "media_id": null, "signed": false },
"status": "draft",
"created_at": "2026-01-01T10:00:00Z",
"updated_at": "2026-01-01T10:00:00Z",
"revoked_at": null,
"revoke_reason": null
}
]
```'
tags:
- Mandates
security:
- BearerAuth: []
parameters:
- name: role
in: query
required: false
description: 'Filter mandates by the user''s role.
- `mandataire` (default): user is the delegate
- `principal`: user is the principal
'
schema:
type: string
enum:
- mandataire
- principal
default: mandataire
example: mandataire
responses:
'200':
description: List of mandates (empty array if none).
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Mandate'
'400':
description: Invalid `role` value.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createMandate
summary: Create a mandate
description: 'Creates a new mandate in `draft` status.
The `tenant_id` and `mandataire_auth_user_id` are derived from the JWT and
must not be supplied in the body.
## Validations
- `principal_kind` must be `owner` or `lessee`
- `scope` must be a non-empty array of valid scope values
- `valid_until`, when present, must be strictly after `valid_from`
## Usage Example
```bash
curl -X POST https://api.faireplace.com/api/mandates \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d ''{
"principal_person_id": "550e8400-e29b-41d4-a716-446655440000",
"principal_kind": "owner",
"scope": ["initiate_signature", "sign_on_behalf"],
"valid_from": "2026-01-01",
"valid_until": "2026-12-31"
}''
```'
tags:
- Mandates
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMandateRequest'
examples:
owner_mandate:
summary: Mandate for an owner
value:
principal_person_id: 550e8400-e29b-41d4-a716-446655440000
principal_kind: owner
scope:
- initiate_signature
- sign_on_behalf
valid_from: '2026-01-01'
valid_until: '2026-12-31'
responses:
'201':
description: Mandate created (status `draft`).
content:
application/json:
schema:
$ref: '#/components/schemas/Mandate'
'400':
description: 'Validation error (invalid `principal_kind`, empty/unknown `scope`,
or `valid_until` not after `valid_from`).
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/mandates/{id}:
get:
operationId: getMandate
summary: Get a mandate
description: 'Retrieves a single mandate by its identifier.
```bash
curl -X GET https://api.faireplace.com/api/mandates/770e8400-e29b-41d4-a716-446655440222 \
-H "Authorization: Bearer YOUR_API_KEY"
```'
tags:
- Mandates
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The mandate.
content:
application/json:
schema:
$ref: '#/components/schemas/Mandate'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/mandates/{id}/attach-document:
post:
operationId: attachDocumentMandate
summary: Attach a document to a mandate
description: 'Attaches a signed document (media) to a mandate. When the attached
document is signed and the mandate is within its validity window, the
mandate is **atomically activated** (status becomes `active`).
```bash
curl -X POST https://api.faireplace.com/api/mandates/770e8400-e29b-41d4-a716-446655440222/attach-document \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d ''{ "media_id": "660e8400-e29b-41d4-a716-446655440111" }''
```'
tags:
- Mandates
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AttachMandateDocumentRequest'
responses:
'200':
description: The updated mandate.
content:
application/json:
schema:
$ref: '#/components/schemas/Mandate'
'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'
/mandates/{id}/activate:
post:
operationId: activateMandate
summary: Activate a mandate
description: 'Activates a `draft` mandate (status becomes `active`). Activation
requires a signed document to be attached and the mandate to be within
its validity window; otherwise the request is rejected.
No request body is required.
```bash
curl -X POST https://api.faireplace.com/api/mandates/770e8400-e29b-41d4-a716-446655440222/activate \
-H "Authorization: Bearer YOUR_API_KEY"
```'
tags:
- Mandates
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The activated mandate (status `active`).
content:
application/json:
schema:
$ref: '#/components/schemas/Mandate'
'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'
/mandates/{id}/revoke:
post:
operationId: revokeMandate
summary: Revoke a mandate
description: 'Revokes a mandate (status becomes `revoked`). An optional `reason`
(max 500 chars) can be provided.
```bash
curl -X POST https://api.faireplace.com/api/mandates/770e8400-e29b-41d4-a716-446655440222/revoke \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d ''{ "reason": "Mandat remplacé par un nouveau" }''
```'
tags:
- Mandates
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/RevokeMandateRequest'
responses:
'200':
description: The revoked mandate (status `revoked`).
content:
application/json:
schema:
$ref: '#/components/schemas/Mandate'
'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'
components:
schemas:
MandateDocumentDto:
type: object
description: The document backing the mandate.
required:
- signed
properties:
media_id:
type:
- string
- 'null'
format: uuid
description: Identifier of the attached media (the signed mandate document).
example: 660e8400-e29b-41d4-a716-446655440111
signed:
type: boolean
description: Whether the mandate document has been signed.
example: false
PrincipalDto:
type: object
description: The principal (person) on whose behalf the mandate is held.
required:
- person_id
- kind
- display_name
properties:
person_id:
type: string
format: uuid
description: Identifier of the principal person (owner or lessee).
example: 550e8400-e29b-41d4-a716-446655440000
kind:
$ref: '#/components/schemas/PrincipalKind'
display_name:
type: string
description: 'Display name of the principal. On creation this is a placeholder
(`(à charger)`) until the principal details are loaded.
'
example: Jean Dupont
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
PrincipalKind:
type: string
description: 'Kind of principal (the person granting the mandate).
'
enum:
- owner
- lessee
x-enumDescriptions:
owner: The principal is a property owner.
lessee: The principal is a lessee (tenant).
example: owner
AttachMandateDocumentRequest:
type: object
description: 'Request to attach a (signed) document to a mandate. Attaching a valid
signed document atomically activates the mandate.
'
required:
- media_id
properties:
media_id:
type: string
format: uuid
description: Identifier of the media (document) to attach.
example: 660e8400-e29b-41d4-a716-446655440111
RevokeMandateRequest:
type: object
description: Request to revoke a mandate.
properties:
reason:
type:
- string
- 'null'
maxLength: 500
description: Optional free-text reason for the revocation.
example: Mandat remplacé par un nouveau
MandateStatus:
type: string
description: 'Lifecycle status of a mandate.
Valid transitions: `draft → active`, `draft → revoked`,
`active → revoked`, `active → expired`.
'
enum:
- draft
- active
- revoked
- expired
example: draft
CreateMandateRequest:
type: object
description: 'Request to create a new mandate. The created mandate starts in `draft`
status. The `tenant_id` and `mandataire_auth_user_id` are derived from the
JWT, never from the body.
'
required:
- principal_person_id
- principal_kind
- scope
- valid_from
properties:
principal_person_id:
type: string
format: uuid
description: Identifier of the principal (owner or lessee) person.
example: 550e8400-e29b-41d4-a716-446655440000
principal_kind:
$ref: '#/components/schemas/PrincipalKind'
scope:
type: array
minItems: 1
description: Non-empty list of delegated permissions.
items:
$ref: '#/components/schemas/MandateScope'
example:
- initiate_signature
- sign_on_behalf
valid_from:
type: string
format: date
description: Start date of validity (ISO 8601).
example: '2026-01-01'
valid_until:
type:
- string
- 'null'
format: date
description: 'Optional end date. Must be strictly after `valid_from` when provided.
'
example: '2026-12-31'
Mandate:
type: object
description: 'A mandate delegating one or more permissions from a principal (owner or
lessee) to a mandataire (the authenticated user). A mandate becomes
`active` once a signed document is attached and it is within its validity
window.
'
required:
- id
- tenant_id
- mandataire_auth_user_id
- principal
- scope
- valid_from
- mandate_document
- status
- created_at
- updated_at
properties:
id:
type: string
format: uuid
description: Unique mandate identifier.
example: 770e8400-e29b-41d4-a716-446655440222
tenant_id:
type: string
description: Tenant identifier (multi-tenant isolation).
example: tenant_123
mandataire_auth_user_id:
type: string
description: Auth user ID of the mandataire (extracted from the JWT).
example: user_456
principal:
$ref: '#/components/schemas/PrincipalDto'
scope:
type: array
description: Ordered list of delegated permissions.
items:
$ref: '#/components/schemas/MandateScope'
example:
- initiate_signature
- sign_on_behalf
valid_from:
type: string
format: date
description: Start date of validity (ISO 8601, `YYYY-MM-DD`).
example: '2026-01-01'
valid_until:
type:
- string
- 'null'
format: date
description: 'End date of validity (ISO 8601). `null` means no end date.
When set, must be strictly after `valid_from`.
'
example: '2026-12-31'
mandate_document:
$ref: '#/components/schemas/MandateDocumentDto'
status:
$ref: '#/components/schemas/MandateStatus'
created_at:
type: string
format: date-time
description: Creation timestamp (ISO 8601).
example: '2026-01-01T10:00:00Z'
updated_at:
type: string
format: date-time
description: Last update timestamp (ISO 8601).
example: '2026-01-01T10:00:00Z'
revoked_at:
type:
- string
- 'null'
format: date-time
description: Revocation timestamp, or `null` if not revoked.
example: null
revoke_reason:
type:
- string
- 'null'
description: Free-text reason for revocation (max 500 chars), or `null`.
example: null
MandateScope:
type: string
description: 'A single permission delegated by the mandate.
'
enum:
- initiate_signature
- sign_on_behalf
- collect_rent
- manage_property
x-enumDescriptions:
initiate_signature: Initiate a signature process on behalf of the principal.
sign_on_behalf: Sign documents on behalf of the principal.
collect_rent: Collect rent on behalf of the principal.
manage_property: Manage the property on behalf of the principal.
example: sign_on_behalf
responses:
Forbidden:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
UnprocessableEntity:
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Not found
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'
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