API
Tout ce que l’application fait sur une villa, une réservation ou un client est accessible en HTTP. Un script — ou un agent — travaille sur les mêmes données que l’interface, sous les mêmes règles, sans session de navigateur.
Cette page est la carte : l’authentification, la forme de chaque réponse, et chaque endpoint avec la page qui le détaille. Chaque endpoint a sa propre page : un appel, ses paramètres, ses réponses et ce qu’il refuse.
Authentification
Chaque requête /api/v1 porte une clé API dans l’en-tête x-api-key. Une clé se crée depuis
Compte → Clés API et appartient à une seule organisation : cette organisation est tout le périmètre
de la clé.
curl -H "x-api-key: $VILLASLOT_API_KEY" \
"https://villaslot.app/api/v1/me"L’organisation n’est jamais dans la requête
Ni dans le corps, ni dans l’URL, ni dans un en-tête. Elle vient de la clé et de rien d’autre. Une
ressource appartenant à une autre organisation répond 404, exactement comme un identifiant qui n’existe pas.
La clé agit comme la personne qui l’a créée
Une clé n’est pas une seconde identité avec ses propres pouvoirs. Elle porte les droits du membre qui l’a créée, dans l’organisation pour laquelle elle a été créée. Rien n’est possible par l’API que la même personne ne pourrait faire dans l’interface — et rien n’est refusé qu’elle pourrait faire.
Une clé cesse de fonctionner quand son porteur quitte l’organisation. Aucun accès
orphelin ne survit à un départ : la clé répond 401 à partir de ce moment, exactement
comme si elle avait été révoquée. Révoquer la clé de quelqu’un qui est parti relève donc
du ménage, pas d’un correctif de sécurité.
Deux questions décident de chaque appel, et les deux doivent passer :
| Question | Décidée par | Réponse en cas d’échec |
|---|---|---|
| Le porteur est-il toujours membre, et avec quel rôle ? | Le porteur de la clé et son rôle | 401 / 403 |
| La ressource appartient-elle à l’organisation de la clé ? | L’organisation de la clé | 404 |
Qui peut faire quoi
| Opération | Rôle minimum dans l’organisation |
|---|---|
| Lire n’importe quoi | member |
| Créer et corriger des clients, créer et gérer des réservations | member |
| Créer, renommer, archiver une villa, sa photo, ses horaires, ses tarifs | admin |
| Modifier les réglages de réservation de l’organisation | admin |
Ce partage n’est pas une décision de l’API : c’est la matrice de permissions du produit lui-même. Un membre est souvent celui qui a le client au téléphone, et le produit réserve la configuration des villas au propriétaire et aux administrateurs de l’organisation.
Enveloppe de réponse
| Cas | Corps |
|---|---|
| Succès | {"success": true, "data": …} |
| Liste paginée | {"success": true, "data": [...], "pagination": {"total", "page", "limit", "totalPages"}} |
| Erreur | {"error": "…"} |
| Erreur de validation | {"error": "…", "details": [ … field-level issues … ]} |
| Refus métier | {"error": "…", "detail": { … reason, names, amounts … }} |
| Statut | Quand |
|---|---|
200 | Lecture ou modification effectuée |
201 | Ressource créée |
401 | Clé absente ou invalide, ou clé dont le porteur a quitté l’organisation |
403 | Le porteur est un membre légitime, mais son rôle est trop bas |
404 | Ressource inconnue, ou ressource d’une autre organisation |
409 | Conflit d’état — un créneau pris, un statut qui a changé, une limite de l’offre atteinte |
413 | Un lot au-delà de sa limite ; le message nomme la limite |
422 | Paramètres ou corps invalides — details liste les champs en cause |
429 | Limite de débit de la clé dépassée (120 requêtes par minute) |
500 | Erreur serveur inattendue |
Une ressource d’une autre organisation répond 404, jamais 403. Un 403
confirmerait que l’identifiant existe. La même réponse pour un identifiant inconnu et pour
un identifiant que vous n’avez pas le droit de lire — vous ne pouvez pas les distinguer, et c’est
voulu. Le 403 est réservé à l’autre question : vous êtes dans la bonne
organisation, votre rôle est trop bas.
Unités et conventions
- Les montants sont des entiers dans l’unité mineure de la devise de l’organisation.
1500000enIDRvaut 15 000 roupies ;4500enEURvaut 45,00 €. Ne divisez jamais par 100 sans connaître la devise. - Les instants sont en ISO 8601 et en UTC (
startAt,endAt,createdAt). - Les jours et les heures sont locaux à l’organisation : une réservation se crée avec
date(YYYY-MM-DD) etstartMinute(minutes depuis minuit local). Lisezsettings.timezonedansGET /api/v1/me. - Les horaires d’ouverture sont des minutes locales hebdomadaires,
dayOfWeekallant de0dimanche …6samedi.
Chaque endpoint
| Méthode | Chemin | Ce qu’il fait | Rôle |
|---|---|---|---|
GET | /api/v1/me | Mon contexte | member |
GET | /api/v1/properties | Lister les villas | member |
POST | /api/v1/properties | Créer une villa | admin |
GET | /api/v1/properties/{propertyId} | Lire une villa | member |
PATCH | /api/v1/properties/{propertyId} | Renommer une villa | admin |
POST | /api/v1/properties/{propertyId}/archive | Archiver une villa | admin |
POST | /api/v1/properties/{propertyId}/photo | Téléverser une photo | admin |
GET | /api/v1/properties/{propertyId}/opening-hours | Lire les horaires d’ouverture | member |
PUT | /api/v1/properties/{propertyId}/opening-hours | Remplacer les horaires d’ouverture | admin |
GET | /api/v1/properties/{propertyId}/rates | Lire la grille tarifaire | member |
PUT | /api/v1/properties/{propertyId}/rates | Remplacer la grille tarifaire | admin |
GET | /api/v1/properties/{propertyId}/availability | Lire les disponibilités | member |
GET | /api/v1/bookings | Lister les réservations | member |
POST | /api/v1/bookings | Créer une réservation | member |
GET | /api/v1/bookings/{bookingId} | Lire une réservation | member |
POST | /api/v1/bookings/{bookingId}/confirm | Confirmer une réservation | member |
POST | /api/v1/bookings/{bookingId}/complete | Terminer une réservation | member |
POST | /api/v1/bookings/{bookingId}/cancel | Annuler une réservation | member |
POST | /api/v1/bookings/{bookingId}/reschedule | Déplacer une réservation | member |
GET | /api/v1/customers | Lister les clients | member |
POST | /api/v1/customers | Créer un client | member |
POST | /api/v1/customers/bulk | Importer des clients | member |
GET | /api/v1/customers/{customerId} | Lire un client | member |
PATCH | /api/v1/customers/{customerId} | Modifier un client | member |
GET | /api/v1/settings/booking | Lire les réglages de réservation | member |
PATCH | /api/v1/settings/booking | Modifier les réglages de réservation | admin |
Limite de débit
La limite est portée par la clé, pas par l’IP : 120 requêtes par minute. Une clé au-delà de sa limite
répond 429 sur tous les endpoints. Ralentissez et réessayez — rien n’a été fait.
Par où commencer
Appelez d’abord GET /api/v1/me : il transforme une simple clé en
contexte — l’organisation qu’elle ouvre, le rôle qu’elle porte, le fuseau horaire et la devise dont dépendent tous les autres
appels, et la marge que laisse l’offre.
Puis le chemin habituel : trouver ou créer le client, demander les disponibilités d’une villa, et créer la réservation. Toute la séquence, avec ses refus, est parcourue dans Créer une réservation.