Vue d’ensemble
L’intégration partenaire sépare le panier et le paiement. Le partenaire ajoute ou modifie les réservations dans une session, puis crée un checkout. RéservPro calcule les montants, héberge la saisie du paiement et publie l’état autoritaire par API et par webhook.
Lecture
- Catégories et nombre de services
- Liste des services
- Détail d’un service
- Variations tarifaires et restrictions
- Emplacements d’un service
- Calendrier rapide des jours complets
Écriture
- Ajout d’une réservation dans une session
- Modification d’une réservation existante
- Transmission des informations complètes du client
- Création idempotente d’un checkout
- Paiement sécurisé dans une iframe RéservPro
- Suivi par polling et webhooks signés
POST /api/reservation avec ajouter ou modifier → POST /api/checkout → affichage de iframe_html ou payment_url → webhook et GET /api/checkout.Exemples pour les outils externes
Télécharger les exemples de réponses en JSON. Ce fichier contient uniquement des données fictives et illustre les structures. Les fiches détaillent les champs conditionnels, les types et les erreurs.
Authentification
Toutes les requêtes doivent être effectuées de serveur à serveur avec la clé du compte marchand. La méthode recommandée est l’en-tête HTTP Authorization: Bearer.
curl 'https://beta.reservpro.com/api/services?Limite=20' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer VOTRE_CLE_API'
IDEntreprise. RéservPro le déduit de la clé. La clé ne doit jamais être intégrée au JavaScript, à l’iframe, à une application cliente distribuée ni enregistrée dans les journaux.api dans la query string ou le corps est encore accepté temporairement, mais peut apparaître dans les journaux et historiques. Toute nouvelle intégration doit utiliser Bearer. Une requête contenant des clés différentes dans plusieurs emplacements est refusée.Format de réponse standard
{
"success": true,
"error": false,
"endpoint": "services",
"IDEntreprise": 123,
"request_id": "req_…",
"data": { ... }
}
Où se trouvent les données?
| Champ | Type JSON | Description |
|---|---|---|
/api/categories | data.details[] | Catégories. |
/api/services | data.Resultats[] | Pagination dans data.details. |
/api/service | data.Service | Vérifier aussi data.Existe. |
/api/variations | data.variations[] ou data.periodes[] | Selon data.mode. |
/api/emplacements | data.services[].Emplacements[] | Pagination dans data.details. |
/api/calendrier | data.jours[] | Clés date et disponible en minuscules. |
/api/disponibilite | data | Vérifier Disponible et Erreur, pas seulement success. |
/api/reservation | data | Panier ou résultat de l’action, selon la méthode. |
/api/checkout | checkout | Exception : l’objet checkout est à la racine, pas dans data. |
/api/gate-access | data | Vérifier valid avant d’autoriser le passage. |
/api/gate-codes | data.codes[] | Codes avec leur contexte. |
/api/gate-history | data.Historique[] | Passages du code exact. |
/api/departs et /api/taches GET | data.Resultats[] | Pagination directement dans data. |
/api/taches PATCH et /api/emplacement-statut | data | Résultat de transition ou état effectif. |
Les schémas historiques ne sont pas uniformes. Les exemples de chaque fiche montrent le format effectivement servi. Les champs supplémentaires doivent être tolérés par les clients pour permettre les enrichissements compatibles.
Sécurité, formats et limites
| Protection | Limite | Comportement |
|---|---|---|
| Corps de requête | 64 Kio (65 536 octets) | Au-delà : 413 payload_too_large. Pour un POST JSON, utiliser Content-Type: application/json. |
| Débit par adresse IP | 600 requêtes par minute | Au-delà : 429 rate_limit_exceeded. |
| Débit par compte marchand | 300 requêtes par minute | Le quota est partagé entre les intégrations utilisant la même clé. |
| Clés invalides | 5 échecs sur 5 minutes | L’adresse IP est bloquée pendant 15 minutes. |
Les réponses incluent un X-Request-ID. Les réponses limitées utilisent 429 et Retry-After; les réponses authentifiées exposent aussi X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset.
customer ou dans metadata. Ces données sont saisies uniquement dans la page de paiement hébergée par RéservPro.Contrat structuré de la bêta — 9 septembre 2026
Les périodes d’ouverture sont des objets avec DateDebut et DateFin. Les prix, frais, dépôts et taxes calculées sont des nombres JSON ou null, sans symbole monétaire. Les taux restent des pourcentages numériques. Les types tarifaires utilisent un slug stable et un libellé séparé.
Les intégrations utilisant l’ancienne bêta doivent adapter la lecture de DatesOuvertures, PeriodeReservationGenerale, PrixHoraire et des montants. PrixBaseFormate est retiré du contrat partenaire; utiliser PrixBase. Type_Tarification est remplacé par type_tarification et type_tarification_texte. Ces changements ne sont pas déployés en production.
Index des endpoints
Choisissez un domaine puis une fiche. Chaque endpoint conserve son lien direct.
Catégories
Retourne les catégories principales, précisions ou sous-précisions. Possibilité de filtrer les catégories ayant des services actifs.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
| parent | string | Non | ID du parent, ex. C12 ou P5. |
| mots_cles | array|string | Non | Mots-clés de recherche. |
| avecServiceActif | bool | Non | Si vrai, retourne seulement les catégories qui ont au moins un service actif. |
Exemple
GET /api/categories?avecServiceActif=1
Authorization: Bearer VOTRE_CLE_API
Réponse HTTP 200 vérifiée
{
"success": true,
"error": false,
"endpoint": "categories",
"IDEntreprise": 9379,
"data": {
"details": [
{
"id": "C346",
"titre": "Activités",
"icone": "fa-basketball",
"nbr_services": 4,
"have_child": true,
"parent_id": null,
"parent_titre": null
},
{
"id": "C303",
"titre": "Camping",
"icone": "fa-campground",
"nbr_services": 5,
"have_child": true,
"parent_id": null,
"parent_titre": null
},
{
"id": "C304",
"titre": "Chalet",
"icone": "fa-house",
"nbr_services": 1,
"have_child": true,
"parent_id": null,
"parent_titre": null
},
{
"id": "C371",
"titre": "Événements ",
"icone": "fa-calendar-day",
"nbr_services": 4,
"have_child": true,
"parent_id": null,
"parent_titre": null
},
{
"id": "C362",
"titre": "Passeport",
"icone": "fa-passport",
"nbr_services": 3,
"have_child": true,
"parent_id": null,
"parent_titre": null
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.details | array<object> | Catégories retournées, [] si aucune. Pas de pagination sur cette route. |
id | string | Identifiant préfixé C, P ou S, utilisable dans IDCategorie et parent. |
titre / icone | string | null | Libellé et icône configurés. |
couleur | string | null · conditionnel | Couleur d’icône pour les précisions et sous-précisions. |
nbr_services | integer | Nombre calculé dans la branche. La branche S retourne actuellement 0 : ne pas interpréter cela comme un inventaire vide. |
have_child | boolean | Indication de navigation. Les précisions P peuvent retourner false même si la route parent=P… expose des sous-précisions; ne pas en faire une preuve d’absence. |
parent_id / parent_titre | string | null | Parent, ou null à la racine. |
Les libellés et nombres de catégories ne remplacent pas la liste filtrée des services effectivement réservables. Charger /api/services pour construire le catalogue.
Liste des services
Retourne les services de l’entreprise avec recherche par mots-clés, pagination et filtres de visibilité/réservabilité.
Paramètres
| Nom | Type | Description |
|---|---|---|
| Mot_Cles | string | Recherche texte libre. |
| IDCategorie | string | Ex. C2, P5, S9. |
| Debut | int | Offset de pagination. |
| Limite | int | Nombre max de résultats. |
| Service_Publie | int | 1 = publié. |
| Service_Reservable_Public | int | 1 = réservable en ligne. |
| Service_Reservable_Interne | int | 1 = réservable à l’interne. |
| En_Vedette | int | 1 = en vedette. |
Exemple
GET /api/services?Service_Publie=1&Service_Reservable_Public=1&Debut=0&Limite=20
Authorization: Bearer VOTRE_CLE_API
Structure de réponse et exemple HTTP 200
Réponse Démo Camping vérifiée le 9 septembre 2026 avec Limite=1, sans filtre de réservation publique. Les lignes sont dans data.Resultats; la pagination dans data.details.
{
"success": true,
"error": false,
"endpoint": "services",
"IDEntreprise": 9379,
"data": {
"details": {
"Message": "",
"Total": 18,
"Debut": 0,
"Limite": 1,
"InclutServicesSupprimes": false,
"InstructionAria": "",
"TravailEnLot": []
},
"Resultats": [
{
"IDService": 31139,
"Titre": "Inventaire Kayak",
"Image": null,
"Description_Courte": "",
"Categorie_Texte": "",
"IDCategorie": "",
"IDSousCategorie": "",
"IDSousSousCategorie": "",
"TypeService": 2,
"EstHebergement": false,
"Prix": 0,
"Quantite": 5,
"Service_Publie": 1,
"Service_Reservable_Public": 0,
"Service_Reservable_Interne": 1,
"Approbation_Manuelle": 0,
"En_Vedette": 0,
"NombreEmplacements": 5,
"NombreHoraires": 0,
"DatesOuvertures": []
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.details.Total / Debut / Limite | integer | Total et pagination. Debut commence à 0; Limite=20 par défaut, entre 1 et 100. |
data.details.Message | string | Précision sur la recherche, éventuellement vide. |
data.details.InclutServicesSupprimes | boolean | Indicateur de recherche spéciale des services supprimés. |
data.details.InstructionAria / TravailEnLot | string / array ou object | Contexte auxiliaire Aria, normalement vide pour une requête partenaire. Ne pas utiliser pour construire le catalogue. |
data.Resultats | array<object> | Services de la page; [] si aucun résultat. |
Champs de data.Resultats[]
| Champ | Type JSON | Description |
|---|---|---|
IDService | integer | Identifiant du service. |
Titre | string | null | Titre enregistré. |
Image | string | null | URL de l’image principale ou null. La fiche utilise Images[]. |
Description_Courte | string | null | Résumé enregistré, éventuellement vide ou null. |
Categorie_Texte | string | Chemin lisible de la catégorie. |
IDCategorie | string | Identifiant préfixé C ou chaîne vide. |
IDSousCategorie | string | Identifiant préfixé P ou chaîne vide. |
IDSousSousCategorie | string | Identifiant préfixé S ou chaîne vide. |
TypeService | integer | Mode natif (nom différent de TypeReservation dans la fiche). |
EstHebergement | boolean | Classement hébergement de la catégorie, distinct du mode de réservation. |
Prix | number | null | Prix numérique sans symbole; null si le moteur n’a pas fourni de prix. La fiche fournit PrixBase. |
Quantite | integer | En horaire : nombre d’emplacements (1 par défaut); autrement : quantité configurée bornée à 0. Pas la disponibilité datée. |
Service_Publie | integer | Indicateur numérique : 1 = publié. |
Service_Reservable_Public | integer | Indicateur numérique : 1 = réservable en ligne. |
Service_Reservable_Interne | integer | Indicateur numérique : 1 = réservable à l’interne. |
Approbation_Manuelle | integer | Indicateur numérique : 1 = approbation manuelle. |
En_Vedette | integer | Indicateur numérique : 1 = en vedette. |
NombreEmplacements | integer | Nombre d’unités configurées. |
NombreHoraires | integer | Nombre d’horaires configurés. |
DatesOuvertures | array<object> | Périodes avec DateDebut et DateFin (YYYY-MM-DD), ou []. |
PrixHoraire | array<object> · conditionnel | Tarifs horaires structurés : DureeHeures (number) et Montant (number ou null), sans texte concaténé. |
Une recherche par mot-clé peut se rabattre sur les emplacements : details.Message l’indique et les lignes peuvent être réduites à IDService, Titre, Categorie, TypeService, Prix (null) et Quantite (0). Charger alors la fiche détaillée.
Détail d’un service
Retourne les détails complets d’un service : description, tarification, images, dépôt, ouverture, taxes, options de réservation et rates OTA si applicables.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
| IDService | int | Oui | ID du service. |
| InclureParametresVides | bool | Non | Défaut : false. Conserve les attributs sans réponse ni choix sélectionné; voir leur structure ci-dessous. |
GET /api/service?IDService=35197
Authorization: Bearer VOTRE_CLE_API
Lire la réponse
data.Service. Vérifier success, puis data.Existe. La liste /api/services utilise data.Resultats[].Exemple de réponse HTTP 200
Réponse HTTP de Démo Camping vérifiée en bêta le 9 septembre 2026. Un seul attribut complémentaire est conservé pour la lisibilité et request_id est remplacé. Les valeurs peuvent évoluer; utilisez un IDService de votre compte.
{
"success": true,
"error": false,
"endpoint": "service",
"IDEntreprise": 9379,
"data": {
"Existe": true,
"Service": {
"IDService": 27644,
"Titre": "Camping 1 service (eau)",
"Categorie_Texte": "Camping > Camping 1 service",
"IDCategorie": "C303",
"IDSousCategorie": "P1680",
"IDSousSousCategorie": "",
"Description": "<p>\r\n\t86 sites de camping aménagés dont 28 sans service avec eau à proximité et 58 sites avec 1 service (eau sur le site).</p>\r\n",
"Quantité": 50,
"TypeReservation": 0,
"EstHebergement": true,
"TypeJours": 0,
"PrixBase": 38,
"SourcePrixBase": "vit_pac.prop_price",
"ReglePrixBase": "Pour un calcul fondé sur le prix de base du service, utiliser PrixBase. Ne pas le remplacer par un montant de DetailsComplementaires, une variation de calendrier, un tarif saisonnier ou un prix futur.",
"Images": [
{
"IDPhoto": 50577,
"URL": "https://beta.reservpro.com/pac/50577.png"
}
],
"Ouverture": "Arrivée possible tous les jours",
"Tarification": [
{
"Montant": 38,
"type_tarification": "par_nuit",
"type_tarification_texte": "Prix par nuit",
"SurDemande": false
},
{
"Montant": 1370,
"type_tarification": "saisonnier",
"type_tarification_texte": "Prix saisonnier",
"SurDemande": false
}
],
"DatesOuvertures": [
{
"DateDebut": "2026-03-01",
"DateFin": "2026-12-31"
}
],
"PeriodeReservationGenerale": {
"DateDebut": "2026-03-01",
"DateFin": "2026-12-31"
},
"Reservation_en_ligne": "Activé",
"Reservation_interne": "Activé",
"Approbation_manuelle": "Désactivé",
"Etat": "Publié",
"Nuit_Minimum": 2,
"Nuit_Maximum": 0,
"Duree_Minimum_WEEK_END": 0,
"Depot_En_Ligne_Pourcentage": 20,
"Depot_Local_Pourcentage": 0,
"Depot_En_Ligne": 0,
"Depot_En_Ligne_Par_Nuit": 0,
"Depot_En_Ligne_Par_Semaine": 0,
"Demander_Age_Enfants": true,
"Demander_Nombre_Participants": true,
"Demander_Noms_Participants": false,
"Appliquer_Les_Taxes_Locales": true,
"Note_Sur_Facture": "",
"Calendrier_ICS_Liaison": "",
"Calendrier_ICS_Liaison_2": "",
"Calendrier_ICS_Liaison_3": "",
"Taxe_Hebergement": null,
"Rates_OTA": [],
"DetailsComplementaires": {
"details": {
"134": {
"ID": 134,
"IDAttribut": 134,
"Parametre": "Nombre d'adultes inclus",
"Suffixe": "",
"Icone": "user-alt",
"Aide": "Le nombre d'adultes inclus dans le prix journalier. Si il n'y a pas de différence en le prix par adulte et enfant n'inscrivez rien dans les sections enfants et adultes.",
"Choix": [],
"Reponse": "2"
}
}
}
}
},
"request_id": "req_exemple"
}Enveloppe de réponse
| Champ | Type JSON | Description |
|---|---|---|
success / error | boolean | Résultat de la requête API. |
endpoint | string | service |
IDEntreprise | integer | Compte déduit de la clé API. |
request_id | string | Identifiant de diagnostic, aussi présent dans X-Request-ID. |
data.Existe | boolean | Indique si la fonction de détail a trouvé la fiche. |
data.Service | object | array vide | Fiche si Existe=true; [] si Existe=false. |
Champs de data.Service
Respectez la casse et les accents. Les champs conditionnels peuvent être absents. Une chaîne vide, null, [] et une clé absente ne sont pas interchangeables.
| Champ | Type JSON | Description |
|---|---|---|
IDService | integer | Identifiant du service. |
Titre | string | null | Titre enregistré. |
Categorie_Texte | string | Chemin lisible de la catégorie. |
IDCategorie | string | Identifiant préfixé C ou chaîne vide. |
IDSousCategorie | string | Identifiant préfixé P ou chaîne vide. |
IDSousSousCategorie | string | Identifiant préfixé S ou chaîne vide. |
Description | string | null | Peut contenir du HTML et des entités HTML. Assainir avant affichage. |
Quantité | number | Quantité configurée, pas la disponibilité à une date donnée. La clé contient un accent. |
TypeReservation | integer | Mode natif : 0 = séjour ou réservation sans multi-horaire; 1 = places par personne avec départs fixes; 2 = horaire lié à un inventaire. Un inventaire lié peut retourner -1 et ne se réserve pas directement. |
EstHebergement | boolean | Classement hébergement de la catégorie, distinct du mode de réservation. |
TypeJours | integer | Mode natif de durée (prop_typenuit), pas une durée. Pour un hébergement, 0 correspond aux nuitées; les autres modes dépendent du parcours. |
PrixBase | number | Prix de base numérique, pouvant valoir 0. Ce n’est pas un devis pour les dates et participants. |
SourcePrixBase | string | Provenance du prix de base. |
ReglePrixBase | string | Consigne de lecture du prix de base. |
Images | array | Conditionnel : absent sans image. Chaque image contient IDPhoto (integer) et URL (string). |
Ouverture | string | Résumé textuel des jours d’arrivée ou d’ouverture. Pas les créneaux ou disponibilités. |
Tarification | array<object> · conditionnel | Lignes avec type_tarification (slug stable), type_tarification_texte (libellé), Montant (number ou null) et SurDemande (boolean). duree_heures (number) pour les tarifs horaires. Voir la liste des types ci-dessous. |
DatesOuvertures | array<object> | Toujours présent; [] sans période précise. Chaque objet contient DateDebut et DateFin (strings YYYY-MM-DD). Aucune concaténation de dates. |
PeriodeReservationGenerale | object | null | Fenêtre générale : DateDebut et DateFin (YYYY-MM-DD), ou null si non configurée. Distincte des périodes précises. |
Reservation_en_ligne | string | « Activé » / « Désactivé » en français, pas un booléen. |
Reservation_interne | string | « Activé » / « Désactivé » en français, pas un booléen. |
Approbation_manuelle | string | « Activé » / « Désactivé » en français, pas un booléen. |
Etat | string | « Publié » / « Non visible » pour une fiche de service. |
Nuit_Minimum | integer | Minimum configuré. Nom historique : tenir compte du mode de durée. |
Nuit_Maximum | integer | Maximum configuré. 0 ne signifie pas que le service est indisponible. |
Duree_Minimum_WEEK_END | integer | Minimum configuré pour la fin de semaine. |
Depot_En_Ligne_Pourcentage | number | Pourcentage, ex. 20 pour 20 %, pas un montant. |
Depot_Local_Pourcentage | number | Pourcentage de dépôt configuré à l’interne. |
Depot_En_Ligne | number | null | Montant numérique sans symbole. null si non renseigné; 0 si zéro. Les variantes de dépôt ne doivent pas être additionnées arbitrairement. |
Depot_En_Ligne_Par_Nuit | number | null | Montant numérique sans symbole. null si non renseigné; 0 si zéro. Les variantes de dépôt ne doivent pas être additionnées arbitrairement. |
Depot_En_Ligne_Par_Semaine | number | null | Montant numérique sans symbole. null si non renseigné; 0 si zéro. Les variantes de dépôt ne doivent pas être additionnées arbitrairement. |
Demander_Age_Enfants | boolean | Demande d’âge des enfants activée. |
Demander_Nombre_Participants | boolean | Demande du nombre de participants activée. |
Demander_Noms_Participants | boolean | Demande des noms activée. |
Appliquer_Les_Taxes_Locales | boolean | Activation des taxes locales, sans leurs taux ni les montants du séjour. |
Note_Sur_Facture | string | null | Texte configuré, éventuellement vide ou null. |
Calendrier_ICS_Liaison | string | Lien de calendrier configuré ou chaîne vide. Ne pas exposer inutilement les liens privés. |
Calendrier_ICS_Liaison_2 | string | Deuxième lien de calendrier ou chaîne vide. |
Calendrier_ICS_Liaison_3 | string | Troisième lien de calendrier ou chaîne vide. |
Taxe_Hebergement | number | null | Taux numérique sans symbole %, ex. 3.5 pour 3,5 %. null si non renseigné. Distinct du montant Montants.TaxeHebergement dans le devis. |
Rates_OTA | array | Plans Booking/Expedia associés, ou []. Structure détaillée ci-dessous. |
DetailsComplementaires | object | Objet contenant details, indexé par identifiant d’attribut. Structure ci-dessous. |
Date_Ouverture | string · conditionnel | Ancien indicateur « Actif » sans fenêtre générale ni période précise; ce n’est pas une date. |
IDInventaire | integer · conditionnel | Présent pour le mode horaire, même si la valeur configurée est 0. |
ID_Service_Liaison | integer · conditionnel | Pour les autres modes, présent si un service lié est configuré. |
Attributs dynamiques : DetailsComplementaires.details
details est un objet indexé par identifiant, par exemple data.Service.DetailsComplementaires.details["134"]. Sans attribut, il vaut []. La liste varie selon la catégorie et la configuration.
| Champ | Type JSON | Description |
|---|---|---|
ID / IDAttribut | integer | Identifiant de l’attribut; ID est conservé pour compatibilité. |
Parametre / Suffixe / Icone / Aide | string | null | Libellé, unité, icône et aide; peuvent être vides. |
Reponse | string | number | null | Valeur de l’attribut. Les attributs monétaires (Suffixe=$) retournent un nombre ou null. Les autres réponses restent textuelles, par exemple « 2 » ou « Oui », selon l’attribut. Le suffixe est une métadonnée séparée du montant. |
Choix | array<object> | Options ou []. Chaque option contient ID (integer), Valeur et Icone (string ou null), Select (boolean). Seuls les choix avec Select=true sont sélectionnés. |
InclureParametresVides=0 (défaut) retire les attributs sans réponse ni choix sélectionné. Avec 1, ils sont conservés sans inventer de valeur. Cette option ne force pas les autres champs conditionnels à apparaître. Un attribut à choix conservé contient aussi les options non sélectionnées.
Plans tarifaires : Rates_OTA[]
| Champ | Type JSON | Description |
|---|---|---|
IDRate / IDChambre_OTA | string | Identifiants externes. |
Source | string | booking ou expedia. |
Titre / TypeRate | string | Libellé et type du plan tarifaire. |
ModeCollecte | integer | null | null pour Booking; code configuré pour Expedia, éventuellement null. Ce bloc ne fournit pas un prix de séjour. |
Exemple de lecture en PHP
// $response = json_decode($body, true);
if (empty($response['success'])) {
throw new RuntimeException($response['error_message'] ?? 'Erreur API');
}
if (empty($response['data']['Existe'])) {
throw new RuntimeException('Fiche de service non disponible');
}
$service = $response['data']['Service'];
$prixBase = $service['PrixBase'];
$images = $service['Images'] ?? [];
$attributs = $service['DetailsComplementaires']['details'] ?? [];
$adultesInclus = $attributs[134]['Reponse'] ?? null;
foreach ($attributs as $attribut) {
// Lire Reponse ou les Choix dont Select vaut true.
}Erreurs et cas particuliers
| Champ | Type JSON | Description |
|---|---|---|
400 · request_error | erreur | IDService absent ou non positif : « IDService est requis. » |
404 · service_not_found | erreur | Service inexistant, étranger au compte ou exclu par le contrôle d’accès. |
200 · data.Existe=false | fiche absente | Un service autorisé peut être exclu par le filtre de date de fin de la fiche. data contient alors {"Existe":false,"Service":[]}. |
401 / 429 / 500 | erreur | Authentification, débit ou erreur interne : voir les erreurs. |
{
"success": false,
"error": true,
"error_code": "service_not_found",
"error_message": "Service introuvable.",
"request_id": "req_exemple"
}Pour calculer une réservation
Cette fiche ne fournit ni un devis complet ni une confirmation de disponibilité. Consulter les unités, les variations tarifaires, le calendrier puis la disponibilité détaillée pour les dates et participants. Ne pas additionner les alternatives de Tarification pour reconstruire le total du séjour.
Types tarifaires stables
type_tarification sert aux conditions dans votre code. type_tarification_texte sert uniquement à l’affichage et peut varier avec la langue. N’utilisez pas le libellé comme identifiant.
| type_tarification | Exemple de type_tarification_texte | Sens |
|---|---|---|
par_nuit | Prix par nuit | Tarif de nuitée. |
par_jour | Prix par jour | Tarif journalier. |
a_partir_de | À partir de | Prix indicatif de départ, pas un devis. |
prix | Prix | Prix général du service. |
tarif | Tarif | Tarif générique, pouvant être gratuit ou sur demande. |
saisonnier | Prix saisonnier | Tarif saisonnier. |
horaire | 2 heures | La durée est séparée dans duree_heures, par exemple 2 ou 0.5. |
autre | Libellé non reconnu | Valeur de repli pour un type natif non encore répertorié; tolérer de nouveaux slugs. |
Une gratuité retourne Montant=0 et SurDemande=false. Un tarif sur demande retourne Montant=null et SurDemande=true. Aucun montant ne contient de symbole monétaire.
Variations
Retourne les variations d’un service entre deux dates. Sur une courte plage, le résultat peut être détaillé jour par jour. Sur une plus grande plage, le résultat peut être regroupé par périodes homogènes.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
| IDService | int | Oui | ID du service. |
| DateDebut | date | Oui | Date de début. |
| DateFin | date | Oui | Date de fin. |
| IDRate | string | Non | Rate externe Booking/Expedia si applicable. |
GET /api/variations?IDService=35197&DateDebut=2026-07-01&DateFin=2026-07-31
Authorization: Bearer VOTRE_CLE_API
Réponse HTTP 200 — aucune variation configurée
{
"success": true,
"error": false,
"endpoint": "variations",
"IDEntreprise": 9379,
"data": {
"mode": "detail",
"IDService": 27644,
"IDRate": "",
"SourceCalendrier": "standard",
"total_jours": 3,
"total": 0,
"variations": [],
"CouvertureLecture": {
"lecture_complete": true,
"DateDebutDemandee": "2026-09-15",
"DateFinDemandee": "2026-09-17",
"jours_demandes": 3,
"jours_avec_variation": 0,
"jours_sans_variation": 3,
"calendrier_entierement_vide": true,
"periodes_sans_variation": [
{
"DateDebut": "2026-09-15",
"DateFin": "2026-09-17",
"Etat": "vide_aucune_variation_configuree"
}
],
"signification_absence": "La date a ete verifiee. Aucune ligne de variation tarifaire ou de disponibilite n est configuree; utiliser les valeurs par defaut du service. Ce n est pas une erreur ni une plage non retournee."
}
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.mode | string | detail jusqu’à 14 dates inclusives; resume au-delà. |
data.IDService / IDRate / SourceCalendrier | integer / string / string | Service, plan tarifaire optionnel et source standard, booking ou expedia. |
data.total_jours | integer | Nombre de dates demandées, bornes incluses. |
data.total | integer | Nombre de lignes en mode detail; nombre de périodes en mode resume. |
data.variations | array<object> · mode detail | Une ligne par date/configuration; [] si aucune variation. |
data.periodes | array<object> · mode resume | Périodes homogènes avec DateDebut, DateFin et params. Remplace variations. |
data.total_lignes | integer · mode resume | Nombre de lignes sources avant regroupement. |
data.CouvertureLecture | object | lecture_complete, DateDebutDemandee, DateFinDemandee, jours_demandes, jours_avec_variation, jours_sans_variation, calendrier_entierement_vide, periodes_sans_variation et signification_absence. |
CouvertureLecture.periodes_sans_variation[] | object | DateDebut, DateFin et Etat=vide_aucune_variation_configuree. |
Champs des variations et de params
| Champ | Type JSON | Description |
|---|---|---|
IDService / Date | integer / string | En mode detail seulement : service et date YYYY-MM-DD. |
Variation_Quantite / Duree_Minimum_Arrivee / Jour_Arrivee / Duree_Minimum_Entre_Reservations | integer | Valeurs natives de variation et de restrictions. Une variation de quantité n’est pas un nombre de places encore disponibles. |
Arrivee_Interdite / Depart_Interdit / Ferme | boolean | Restrictions de la date. |
FraisGestionPourcent | number | Pourcentage de frais configuré. |
Prix / Duree_Minimum / Duree_Maximum | number / integer / integer | Pour le mode séjour (TypeReservation=0). |
IDHoraire | integer · conditionnel | Pour les autres modes, identifiant du créneau. |
Prix_Adulte / Prix_Enfant / Prix_Etudiant / Prix_Aine / Prix_Petit_Enfant / Prix_Famille | number · conditionnel | Tarifs par catégorie pour les activités/horaires; tarifs complémentaires aussi possibles en mode OTA séjour. |
Prix_Grand_Enfant | number · conditionnel | Si disponible dans le schéma et pour les modes concernés. |
IDRate | string · conditionnel | Plan tarifaire en mode OTA. |
Une période sans variation signifie que la lecture a bien couvert les dates et que les valeurs du service s’appliquent; elle n’est pas automatiquement fermée. La disponibilité détaillée reste l’autorité pour le prix réservable.
Emplacements
Retourne la liste des emplacements associés à un service. Possibilité d’inclure des dates pour obtenir une première lecture rapide de disponibilité par emplacement.
Paramètres
| Nom | Type | Description |
|---|---|---|
| IDService | int | Service visé. |
| MotsCles | array|string | Recherche sur les emplacements. |
| Debut | int | Offset. |
| Limite | int | Nombre max. |
| DateDebut | date | Date début pour lecture de disponibilité. |
| DateFin | date | Date fin. |
| IDReservation | int | Réservation à exclure dans une logique de modification. |
GET /api/emplacements?IDService=35197&DateDebut=2026-07-10&DateFin=2026-07-15
Authorization: Bearer VOTRE_CLE_API
Filtres complémentaires
| Champ | Type JSON | Description |
|---|---|---|
AvecDescription | boolean | Défaut false. Avec 1, inclut Description dans les unités. |
Nbr_Adulte / Nbr_Enfant / Nbr_Chien | integer | Défaut 0. Filtre les limites propres aux unités; ne remplace pas la validation du service ni des équipements. |
DateDebut / DateFin | string | Fournir les deux dates ou aucune. DateFin doit être strictement postérieure à DateDebut; sinon HTTP 422. |
Réponse HTTP 200 vérifiée — sans dates
{
"success": true,
"error": false,
"endpoint": "emplacements",
"IDEntreprise": 9379,
"data": {
"details": {
"Total": 1,
"TotalEmplacementsDisponibles": null,
"Debut": 0,
"Limite": 1
},
"services": [
{
"IDService": "27644",
"TitreService": "Camping 1 service (eau)",
"Categorie": "Camping Camping 1 service",
"TypeService": "0",
"Emplacements": [
{
"IDEmplacement": "8551",
"Titre": "Frontenac # 01",
"PlanX": "263",
"PlanY": "903",
"DateDebutValidite": "0000-00-00",
"DateFinValidite": "0000-00-00",
"EnLigne": true,
"EstSaisonnier": false,
"MinGrandeur": 0,
"MaxGrandeur": 20,
"MaxChien": -1,
"MaxPerson": 0,
"MaxAdulte": -1,
"MaxEnfant": -1,
"Menage": {
"Statut": "inconnu",
"Libelle": "Ménage non confirmé",
"Pret": null,
"TachesOuvertes": 0,
"IDTaches": [],
"DerniereCompletion": null
}
}
]
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.details.Total | integer | Nombre d’emplacements retournés sur la page, après filtrage daté si applicable. Ce n’est pas le total global du catalogue. |
data.details.TotalEmplacementsDisponibles | integer | null | Nombre retourné avec dates; null sans dates. |
data.details.Debut / Limite | integer | Offset et taille demandée; défaut 0 / 20, maximum 100. Le filtrage de disponibilité intervient après la sélection de la page SQL : une page courte ou vide ne prouve pas la fin des résultats. |
data.services | array<object> | Unités regroupées par service ou inventaire lié; [] si aucun groupe. |
services[].IDService / TypeService | string | Identifiants numériques historiques sous forme de chaînes. |
services[].TitreService / Categorie | string | null | Libellés du service. |
services[].UtiliseParIDService | array<string> · conditionnel | Services liés à un inventaire. |
services[].Emplacements | array<object> | Unités de ce groupe; peut être vide après filtrage. |
Emplacements[].IDEmplacement | string | Identifiant de l’unité. |
Titre / Description | string | null | Description conditionnelle : AvecDescription=1. |
PlanX / PlanY | string | null | Coordonnées natives sur le plan, désormais présentes aussi sans dates. Leur échelle dépend du fond de plan du service. |
DateDebutValidite / DateFinValidite | string | MM-DD si configuré, sinon « 0000-00-00 ». Ce ne sont pas des dates ISO complètes. |
EnLigne / EstSaisonnier | boolean | Indicateurs configurés. Avec dates, les unités saisonnières et les unités hors état normal sont exclues. |
MinGrandeur / MaxGrandeur / MaxPerson / MaxAdulte / MaxEnfant / MaxChien | integer | Restrictions configurées. Les sentinelles dépendent du champ : MaxPerson<=0 sans limite propre; MaxAdulte/MaxEnfant/MaxChien<0 sans limite propre, 0 n’autorise aucun participant de cette catégorie. |
CodeBoiteCle | string · conditionnel | Code privé de boîte à clés, si configuré. Ne pas l’afficher dans un catalogue public. |
IDUtilisateur | integer | string · conditionnel | Utilisateur assigné à l’unité. |
Menage | object | Statut, Libelle, Pret (boolean ou null), TachesOuvertes (integer), IDTaches (array |
Avec dates, seules les unités sans chevauchement d’affectation sont retournées. Pour les capacités globales, les équipements et le tarif, utiliser /api/disponibilite. Le ménage ne bloque pas commercialement les réservations futures.
Calendrier rapide
Endpoint recommandé pour permettre à un partenaire de construire rapidement un calendrier de disponibilité sur les 30 prochains jours. Cet endpoint peut utiliser une fonction interne très rapide qui retourne les jours non disponibles d’un service, et optionnellement d’un emplacement précis via IDEmplacement.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
| IDService | int | Oui | ID du service. |
| DateDebut | date | Non | Défaut suggéré : aujourd’hui. |
| DateFin | date | Non | Défaut suggéré : 30 jours après DateDebut. |
| IDEmplacement | int | Non | Permet de cibler un emplacement précis. |
Réponse HTTP 200 vérifiée
{
"success": true,
"error": false,
"endpoint": "calendrier",
"IDEntreprise": 9379,
"data": {
"success": true,
"IDService": 27644,
"IDEmplacement": 0,
"jours": [
{
"date": "2026-09-15",
"disponible": true
},
{
"date": "2026-09-16",
"disponible": true
},
{
"date": "2026-09-17",
"disponible": true
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.success | boolean | Résultat du calcul rapide. |
data.IDService / data.IDEmplacement | integer | Service et emplacement demandés; IDEmplacement=0 signifie aucun emplacement précis. |
data.jours | array<object> | Un élément pour chaque date, bornes incluses. |
data.jours[].date | string | Date YYYY-MM-DD, clé en minuscules. |
data.jours[].disponible | boolean | Première indication de disponibilité, sans devis ni garantie pour un groupe ou un séjour complet. |
Les anciennes clés suggérées Jours, JoursComplets, Date et Disponible ne font pas partie de ce retour. Les valeurs par défaut sont aujourd’hui et DateDebut + 30 jours (31 dates avec les deux bornes). L’écart maximal entre les dates est de 62 jours. Valider le séjour complet via la disponibilité détaillée.
Disponibilité détaillée
Vérifie la disponibilité et calcule le prix d’un séjour ou d’une activité précise. Peut recevoir un IDEmplacement dans Details.
/api/calendrier.Corps JSON
{
"IDService": 35197,
"Details": {
"Date_Debut": "2026-07-10",
"Date_Fin": "2026-07-15",
"Nbr_Adulte": 2,
"Nbr_Enfant": 1,
"Nbr_Etudiant": 0,
"Nbr_Aine": 0,
"Nbr_PetitEnfant": 0,
"Nbr_GrandEnfant": 0,
"IDEmplacement": 8832,
"HeureDebut": 0,
"HeureDuree": 0
}
}
Réponse HTTP 200 vérifiée
Exemple Démo Camping pour le 15 au 17 septembre 2026, avec Nbr_Adulte=2. Le calcul ne crée pas de réservation.
{
"success": true,
"error": false,
"endpoint": "disponibilite",
"IDEntreprise": 9379,
"data": {
"IDService": 27644,
"TypeReservation": "0",
"Disponible": true,
"NbrDisponible": 17,
"SousTotal": 76,
"Frais": 3.5,
"Total": 91.41,
"Montants": {
"SousTotal": 76,
"Frais": 3.5,
"Taxe1": 3.975,
"Taxe2": 7.93,
"TaxeHebergement": 0,
"Rabais": 0,
"Depot": 18.28,
"DepotSecurite": 0,
"Total": 91.41
},
"Avertissement": "",
"DisponibiliteParJour": 17,
"Erreur": ""
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.IDService | integer | Service évalué. |
data.TypeReservation | string · conditionnel | Mode natif retourné par la base, ex. « 0 ». Peut être absent si la fiche est introuvable dans le moteur. |
data.Disponible | boolean | true uniquement si le moteur indique une disponibilité et aucune erreur métier. Un dépassement de capacité retourne false même s’il reste des unités. |
data.NbrDisponible | number | null | Quantité restante selon le mode, si fournie par le moteur. |
data.SousTotal / Frais / Total | number | null | Montants numériques sans symbole. Le bloc Montants complète ces valeurs avec les taxes, rabais et dépôts. |
data.Montants | object · conditionnel | Bloc numérique ajouté en bêta; absent si le service n’est pas trouvé par le moteur. |
data.Montants.SousTotal / Frais / Taxe1 / Taxe2 / TaxeHebergement / Rabais / Depot / DepotSecurite / Total | number | null | Valeurs directement issues du moteur. Taxe1, Taxe2 et TaxeHebergement sont des montants, jamais des taux. null signifie valeur non fournie, pas zéro. |
data.Avertissement / Erreur | string | Messages métier, éventuellement vides; plusieurs messages peuvent être séparés par |. |
data.DisponibiliteParJour | number | null | Malgré son nom historique, le retour actuel est une quantité synthétique, pas une liste de dates. Utiliser /api/calendrier pour une grille. |
Conserver le total calculé par le moteur. Les taxes peuvent garder une précision intermédiaire (ex. 3.975); ne pas reconstruire le total à partir de montants arrondis séparément. Les rabais et dépôts ne sont pas des montants à ajouter au total. La disponibilité peut changer avant la création du panier.
Paramètres de Details
| Champ | Type JSON | Description |
|---|---|---|
Date_Debut / Date_Fin | string | Dates YYYY-MM-DD. Date_Debut requise; Date_Fin prend Date_Debut si omise. Le mode de réservation détermine si une même journée est valide. Écart maximal : 62 jours. |
Nbr_Adulte / Nbr_Enfant / Nbr_Etudiant / Nbr_Aine / Nbr_PetitEnfant / Nbr_GrandEnfant | integer | Nombres de participants par catégorie native. Utiliser ces noms exacts; Nombre_Adultes n’est pas l’alias de Nbr_Adulte. |
IDEmplacement / IDHoraire | integer | Unité ou créneau correspondant au service, selon le parcours. |
Nbr_Chien / Nbr_Vehicule / Nbr_VehiculeElectrique | integer | Quantités supplémentaires prises en compte selon la configuration. |
CodePromo / CodeMembre | string | Code promotionnel ou membre, selon les règles du commerce. |
IDReservation | integer · conditionnel | Pour évaluer une modification; fournir aussi IDSession au niveau racine. La réservation doit appartenir à la session et au compte. |
Réservation
Endpoint principal permettant soit de consulter une réservation ou un panier de session en GET,
soit d’ajouter ou modifier les éléments du panier en POST. La transmission du client et le passage au paiement se font exclusivement avec POST /api/checkout.
GET — Consulter une réservation ou un panier
Retourne soit le panier complet d’une session, soit une réservation précise appartenant à cette session.
Cet endpoint ne dépend pas de $_SESSION['idusr'] : l’entreprise est déterminée automatiquement à partir de la clé API.
Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
IDSession |
string | Oui | Identifiant de session utilisé pour le panier ou la réservation : 16 à 44 lettres, chiffres, tirets ou soulignements. |
IDReservation |
integer | Non | Si fourni, retourne uniquement cette réservation. Sinon, retourne tout le panier de la session. |
Exemple — panier complet
GET /api/reservation?IDSession=campingqc_123abc
Authorization: Bearer VOTRE_CLE_API
Exemple — réservation précise
GET /api/reservation?IDSession=campingqc_123abc&IDReservation=2786491
Authorization: Bearer VOTRE_CLE_API
Exemple de réponse — panier
{
"success": true,
"error": false,
"endpoint": "reservation",
"IDEntreprise": 123,
"data": {
"success": true,
"error": false,
"details": {
"IDSession": "campingqc_123abc",
"TotalReservations": 2,
"SousTotalPanier": 540,
"TotalPanier": 620.87
},
"Reservations": [
{
"IDReservation": 2786491,
"IDService": 35197,
"TitreService": "Terrain 3 services",
"Reservation_Date_Debut": "2026-07-10",
"Reservation_Date_Fin": "2026-07-15",
"Nombre_Adultes": 2,
"Nombre_Enfants": 1,
"Quantite": 1,
"Status": "Panier",
"SousTotal": 270,
"Total": 310.44,
"Emplacements": [
{
"IDEmplacement": 8832,
"TitreEmplacement": "Terrain A-12",
"DateDebut": "2026-07-10",
"DateFin": "2026-07-15"
}
],
"Elements_Associes": []
}
]
},
"request_id": "req_exemple"
}
POST — Gérer une réservation
Le champ action accepte uniquement ajouter ou modifier. Une confirmation doit passer par le checkout; l’annulation ne fait pas partie de ce contrôleur partenaire.
Pour une modification, IDReservation doit appartenir au compte authentifié et à IDSession. IDService peut être omis pour conserver le service courant; s’il est fourni, il doit appartenir au même compte. Un IDEmplacement doit appartenir à ce service. Toute référence étrangère est retournée comme introuvable.
Actions supportées
| Action | Description |
|---|---|
ajouter |
Ajoute une ou plusieurs réservations dans une session. |
modifier |
Modifie une réservation existante via IDReservation. |
action=confirmer est retirée et retourne 410 confirmation_endpoint_retired. N’envoyez pas action=annuler; utilisez le mécanisme de gestion approprié hors de ce parcours partenaire.Exemple — ajouter
{
"action": "ajouter",
"IDSession": "campingqc_123abc",
"reservations": [
{
"IDService": 35197,
"IDEmplacement": 8832,
"Date_Debut": "2026-07-10",
"Date_Fin": "2026-07-15",
"Nbr_Adulte": 2,
"Nbr_Enfant": 1
}
]
}
Exemple — modifier
{
"action": "modifier",
"IDSession": "campingqc_123abc",
"reservations": [
{
"IDReservation": 2786491,
"IDService": 35197,
"IDEmplacement": 8832,
"Date_Debut": "2026-07-11",
"Date_Fin": "2026-07-16",
"Nbr_Adulte": 2,
"Nbr_Enfant": 1
}
]
}
Checkout partenaire
Crée une photographie sécurisée du panier, associe le client aux réservations et retourne l’URL de paiement hébergée. Les montants sont recalculés par RéservPro; le partenaire ne transmet aucun montant à débiter.
Idempotency-Key unique d’au moins 8 caractères pour chaque nouveau checkout. En cas de délai réseau, répéter exactement la même requête avec la même clé. Ne jamais réutiliser cette clé pour un autre panier ou un autre client.En-têtes
Authorization: Bearer VOTRE_CLE_API
Content-Type: application/json
Accept: application/json
Idempotency-Key: cq-commande-20260710-000123
Corps JSON
| Champ | Type | Requis | Description |
|---|---|---|---|
IDSession | string | Oui | Session du panier préalablement construit avec /api/reservation. |
customer | object | Oui | Coordonnées complètes du client; voir le tableau suivant. |
iframe_origin | string | Oui | Origine exacte qui intégrera l’iframe, par exemple https://reservation.partenaire.ca. Ne pas inclure de chemin. |
webhook_url | string | Recommandé | URL HTTPS publique sur le port 443 qui recevra les changements d’état. Les identifiants dans l’URL, les redirections et les adresses privées ou réservées sont refusés. |
webhook_secret | string | Non | Secret de signature de 24 à 512 caractères. S’il est omis avec une URL webhook, RéservPro en génère un dans la réponse de création ou de reprise idempotente; il n’est jamais publié par GET. |
partner_reference | string | Non | Référence stable du partenaire, utile pour le rapprochement; maximum 191 caractères. |
metadata | object | Non | Données métier non sensibles, maximum 16 Kio. Ne jamais y placer de donnée de carte. |
expires_in | integer | Non | Durée de validité en secondes, de 300 à 86 400; défaut : 1 800 secondes. |
Objet customer
| Champ | Requis | Description |
|---|---|---|
first_name, last_name | Oui | Prénom (50 caractères) et nom (75 caractères). |
email, phone | Oui | Courriel valide (100 caractères) et téléphone (20 caractères). |
company | Non | Entreprise du client, maximum 75 caractères. |
phone2, fax | Non | Second téléphone et télécopieur, maximum 20 caractères chacun. |
address1, city, state, country, postal_code | Oui | Adresse de facturation ou de réservation. Limites respectives : 200, 50, 12, 50 et 12 caractères; utiliser un code court comme QC pour state. |
address2 | Non | Complément d’adresse, maximum 100 caractères. |
language | Non | fr ou en; défaut fr. |
client_id | Non | Identifiant d’un client qui appartient déjà au compte marchand. |
driver_license, driver_license_expiry, arrival_time | Non | Informations complémentaires lorsque requises par l’établissement; limites : 25, 10 et 10 caractères. |
communication, sms_communication | Non | Préférences de communication. Valeurs acceptées : -2, 0 ou 1; défaut 0. |
client_type | Non | Type de client sous forme d’entier positif, maximum 8 388 607. |
reference | Non | Référence numérique, de 0 à 32 767. |
note | Non | Note interne associée au client, maximum 4 000 caractères. |
Une valeur qui dépasse sa limite est refusée avec HTTP 422 invalid_checkout; elle n’est jamais tronquée silencieusement.
metadata.Exemple cURL — créer le checkout
curl -X POST 'https://beta.reservpro.com/api/checkout' \
-H 'Authorization: Bearer VOTRE_CLE_API' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Idempotency-Key: cq-commande-20260710-000123' \
--data '{
"IDSession": "campingqc_123abc",
"customer": {
"first_name": "Hugo",
"last_name": "Girard",
"email": "hugo@example.com",
"phone": "514-555-0199",
"address1": "123 rue Exemple",
"address2": "",
"city": "Montréal",
"state": "QC",
"country": "Canada",
"postal_code": "H1H 1H1",
"language": "fr"
},
"iframe_origin": "https://reservation.partenaire.ca",
"webhook_url": "https://reservation.partenaire.ca/webhooks/reservpro",
"webhook_secret": "whsec_EXEMPLE_A_REMPLACER_32_CARACTERES",
"partner_reference": "CQ-2026-000123",
"metadata": {
"channel": "camping-quebec"
}
}'
Réponse de création
{
"success": true,
"error": false,
"endpoint": "checkout",
"request_id": "req_…",
"checkout": {
"id": "chk_…",
"partner_reference": "CQ-2026-000123",
"metadata": {
"channel": "camping-quebec"
},
"status": "payment_pending",
"status_url": "https://beta.reservpro.com/api/checkout?IDCheckout=chk_…",
"version": 1,
"reservation_ids": [
2786491
],
"invoice_ids": [],
"invoices": [],
"item_count": 1,
"amount_total": 310.44,
"amount_due": 155.22,
"amount_paid": 0,
"balance_due": 155.22,
"currency": "CAD",
"payment_required": true,
"payment_completed": false,
"payment_url": "https://beta.reservpro.com/api/payment/rpt_…",
"iframe_html": "<iframe src=\"https://beta.reservpro.com/api/payment/rpt_…\" …></iframe>",
"iframe_origin": "https://reservation.partenaire.ca",
"payment_origin": "https://reservpro.com",
"payment_gateway": "stripe",
"expires_at": "2026-07-10T15:00:00-04:00",
"paid_at": null,
"completed_at": null,
"released_at": null,
"created_at": "2026-07-10T14:30:00-04:00",
"updated_at": "2026-07-10T14:30:00-04:00",
"checkout_token": "rpt_…",
"idempotent_replay": false
}
}
Une création retourne HTTP 201; une reprise idempotente retourne 200 avec idempotent_replay: true. status_url exige toujours l’authentification Bearer. checkout_token est la capacité temporaire déjà intégrée à payment_url; ne la transmettez jamais ailleurs. Si RéservPro génère webhook_secret, il apparaît dans la création et ses reprises idempotentes, mais jamais dans un GET. Stockez-le immédiatement dans un gestionnaire de secrets.
GET — consulter l’état
curl --get 'https://beta.reservpro.com/api/checkout' \
-H 'Authorization: Bearer VOTRE_CLE_API' \
-H 'Accept: application/json' \
--data-urlencode 'IDCheckout=chk_…'
La réponse place l’état dans checkout et reprend les montants, références et dates. Pour ne pas republier le jeton de paiement, payment_url et iframe_html valent null lors d’un GET. Conservez la réponse de création; si elle est perdue après un délai réseau, répétez le même POST avec la même clé d’idempotence. Une ressource d’un autre compte marchand retourne une réponse introuvable.
États possibles
| État | Terminal | Signification |
|---|---|---|
payment_pending | Non | Le checkout attend un paiement dans l’interface hébergée. |
confirmation_pending | Non | Aucun paiement n’est requis, mais le client doit encore confirmer dans l’interface hébergée afin de finaliser la réservation et sa facture. |
paid | Oui | Le paiement a été validé et enregistré par RéservPro. |
completed | Oui | La confirmation sans paiement a été finalisée et la facture a été créée. |
failed | Réservé | État prévu pour une évolution future; il n’est pas produit par le parcours actuel. |
expired | Oui | Le délai est dépassé et aucun nouveau paiement ne peut être commencé. Un retour fournisseur déjà engagé peut encore être rapproché pendant la grâce interne; le statut autoritaire peut alors devenir paid. |
cancelled | Oui | Les réservations du checkout ne sont plus actives. |
Après expiration, RéservPro conserve le snapshot pendant une grâce de 15 minutes par défaut afin de rapprocher un paiement déjà engagé. Sans preuve de paiement, le worker restaure ensuite atomiquement les réservations dans le IDSession partenaire et renseigne released_at. Pour reprendre les mêmes éléments, attendez que released_at ne soit plus null, puis créez un checkout avec une nouvelle clé d’idempotence. L’événement de restauration utilise checkout.updated.
GET /api/checkout ou par un webhook RéservPro validé. Ne concluez jamais qu’un paiement est réussi à partir d’une redirection du navigateur.Iframe de paiement
Le champ iframe_html contient une iframe prête à intégrer. payment_url peut aussi être utilisé comme attribut src ou ouvert dans une page dédiée. Cette URL contient une capacité temporaire : ne la journalisez pas, ne la modifiez pas et ne la partagez pas.
iframe_origindoit être l’origine HTTPS exacte de la page parente : schéma, hôte et port, sans chemin, query string ni fragment.- La page de paiement applique une politique CSP
frame-ancestorslimitée à cette origine. Une intégration depuis une autre origine est refusée par le navigateur. - La clé API Bearer reste sur le serveur partenaire et n’est jamais transmise à l’iframe.
- Les messages
postMessage, lorsqu’ils sont utilisés, servent uniquement à mettre à jour l’interface. Le parent doit validerevent.origin,event.sourceet la structure du message. - Un message navigateur, une fermeture d’iframe ou une URL de retour ne constitue jamais une preuve de paiement. Après tout signal UX, interroger
GET /api/checkout.
Message de mise à jour de l’iframe
{
"type": "reservpro.checkout.status",
"checkout_id": "chk_…",
"status": "paid",
"payment_completed": true
}
Le message est envoyé uniquement à iframe_origin. Dans la page parente, conserver une référence vers l’élément iframe et accepter le message seulement si event.origin correspond exactement à payment_origin, si event.source === iframe.contentWindow, si checkout_id est celui attendu et si le schéma ci-dessus est valide. Le serveur partenaire doit ensuite confirmer l’état avec le GET authentifié; le navigateur ne doit jamais appeler l’API avec la clé Bearer.
Webhooks de checkout
Lorsqu’un webhook_url est fourni à la création, RéservPro envoie les événements de checkout par POST JSON. Les types actuels comprennent checkout.created — dont le checkout peut être payment_pending ou confirmation_pending — puis checkout.paid, checkout.completed, checkout.expired, checkout.cancelled et, lors d’une autre évolution matérielle, checkout.updated. L’état et l’événement failed sont réservés à une évolution future.
En-têtes de livraison
Content-Type: application/json
X-ReservPro-Event: checkout.paid
X-ReservPro-Event-ID: evt_…
X-ReservPro-Timestamp: 1783711800
X-ReservPro-Signature: v1=SIGNATURE_HEXADECIMALE
Corps type
{
"id": "evt_…",
"type": "checkout.paid",
"created_at": "2026-07-10T18:10:00Z",
"data": {
"checkout": {
"id": "chk_…",
"partner_reference": "CQ-2026-000123",
"status": "paid",
"version": 2,
"amount_due": 155.22,
"amount_paid": 155.22,
"balance_due": 0,
"currency": "CAD"
}
},
"context": {
"previous_status": "payment_pending"
}
}
Validation de la signature
La signature est calculée sur les octets exacts du corps reçu : HMAC_SHA256(timestamp + "." + raw_body, webhook_secret). Comparez v1=… en temps constant, refusez les timestamps trop anciens et ne recomposez jamais le JSON avant la validation.
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_RESERVPRO_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_RESERVPRO_SIGNATURE'] ?? '';
$eventId = $_SERVER['HTTP_X_RESERVPRO_EVENT_ID'] ?? '';
$secret = getenv('RESERVPRO_WEBHOOK_SECRET');
if (!is_string($secret) || $secret === '' || !preg_match('/^\d{10}$/D', $timestamp)) {
http_response_code(401);
exit;
}
if (abs(time() - (int) $timestamp) > 300) {
http_response_code(401);
exit;
}
$expected = 'v1=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
$event = json_decode($rawBody, true, 64, JSON_THROW_ON_ERROR);
if (!is_array($event) || !preg_match('/^evt_[A-Za-z0-9_-]+$/D', $eventId)
|| ($event['id'] ?? '') !== $eventId) {
http_response_code(400);
exit;
}
// Enregistrer $eventId avec une contrainte UNIQUE avant le traitement métier.
// Si $eventId existe déjà, répondre 2xx sans retraiter l’événement.
http_response_code(204);
X-ReservPro-Event-ID peut donc être reçu plusieurs fois. Persistez l’événement, dédupliquez-le, répondez rapidement avec un code 2xx et traitez le métier de façon idempotente.data.checkout.version et confirmez toujours l’état courant avec GET /api/checkout?IDCheckout=…. Le polling demeure le mécanisme de secours lorsqu’un webhook tarde ou échoue.Validation d’accès
Endpoint permettant de valider un code d’accès pour autoriser ou refuser un passage. Le code peut être lié à un accès saisonnier ou à une réservation active.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
code |
string | Oui | Code d’accès à valider. |
type |
integer | Non | Type de validation. 0 = entrée, 1 = sortie. Défaut : 0. |
save_log |
boolean | Non | Indique si la validation doit être enregistrée dans RéservPro. Défaut : true. |
Exemple — POST JSON
{
"code": "ABC123",
"type": 0,
"save_log": true
}
Réponse — accès saisonnier autorisé
{
"success": true,
"error": false,
"endpoint": "gate-access",
"IDEntreprise": 123,
"data": {
"valid": true,
"type": "saisonnier",
"message": "Accès saisonnier valide.",
"access": {
"code_access": "ABC123",
"validation_type": "entree",
"id_validation": 456
},
"saisonnier": {
"saison_id": 987,
"saison_datedebut": "2026-05-01",
"saison_datefin": "2026-10-15"
},
"site": {
"IDEmplacement": 8832,
"Nom": "Terrain A-12"
},
"client": {
"usr_id": 789,
"nom": "Jean Tremblay",
"email": "jean@example.com"
},
"vehicule": {
"vps_id": 321,
"type": "Automobile",
"marque": "Toyota",
"model": "RAV4",
"couleur": "Noir",
"annee": "2020",
"plaque": "ABC123",
"no_serie": "",
"vignette": 1,
"no_acces": "ABC123",
"conducteur": "Marie Tremblay",
"informations": ""
}
},
"request_id": "req_exemple"
}
Réponse — accès réservation autorisé
{
"success": true,
"error": false,
"endpoint": "gate-access",
"IDEntreprise": 123,
"data": {
"valid": true,
"type": "reservation",
"message": "Accès réservation valide.",
"access": {
"code_access": "XYZ789",
"validation_type": "entree",
"id_validation": 457
},
"reservation": {
"reserv_id": 2786491,
"reserv_datedebut": "2026-07-10",
"reserv_datefin": "2026-07-15",
"reserv_actif": 1,
"reserv_inv": 1433936
},
"gate_data": {
"id": 55,
"modified": 0
}
},
"request_id": "req_exemple"
}
Réponse — accès refusé
{
"success": true,
"error": false,
"endpoint": "gate-access",
"IDEntreprise": 123,
"data": {
"valid": false,
"type": "",
"message": "Accès refusé : aucun saisonnier ou réservation active trouvé pour ce code.",
"access": {
"code_access": "ABC123",
"validation_type": "entree"
}
},
"request_id": "req_exemple"
}
Champs de réponse
| Champ | Type | Description |
|---|---|---|
valid |
boolean | Indique si le code donne accès ou non. |
type |
string | Type d’accès reconnu. Valeurs possibles : saisonnier ou reservation. |
site |
object | Emplacement associé. Pour un saisonnier, provient de vit_pac_saisonnier.saison_idplan. Pour une réservation, peut être obtenu via l’assignation d’emplacement. |
vehicule |
object | Informations du véhicule lorsque le code correspond à une carte d’accès véhicule : type, marque, modèle, couleur, année, plaque et conducteur. |
client |
object | Client lié au badge ou à la réservation. |
Exemple PHP / cURL
$payload = [
'code' => 'ABC123',
'type' => 0,
'save_log' => true
];
$ch = curl_init('https://beta.reservpro.com/api/gate-access');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Authorization: Bearer VOTRE_CLE_API',
'Content-Type: application/json'
],
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (!empty($data['data']['valid'])) {
echo 'Accès autorisé';
} else {
echo 'Accès refusé';
}
Informations et historique ajoutés en bêta
La réponse conserve ses champs existants et ajoute sites (toutes les affectations d’une réservation), validite, FuseauHoraire et Historique : les cinq passages précédant la validation courante. HistoriqueAvantValidation=true précise ce moment. save_log=false vérifie sans enregistrer de passage.
La validité native est vérifiée par jour, avec bornes inclusives. Les dates ne représentent pas des heures d’ouverture précises. Les réservations annulées sont refusées. Voir la fiche de l’historique pour les anciens logs incomplets.
Liste des codes d’accès
Endpoint permettant d’obtenir la liste des codes d’accès assignés aux réservations. Il peut être utilisé par un système de contrôle d’accès pour synchroniser ou consulter les accès actifs sur une période donnée.
Paramètres
| Nom | Type | Requis | Description |
|---|---|---|---|
DateDebut |
date | Non | Date de début du filtre. Format recommandé : YYYY-MM-DD. |
DateFin |
date | Non | Date de fin du filtre. Format recommandé : YYYY-MM-DD. |
IDReservation |
integer | Non | Permet de retourner les codes d’une réservation précise. |
code |
string | Non | Permet de rechercher un code précis. |
Debut |
integer | Non | Position de départ pour la pagination. Défaut : 0. |
Limite |
integer | Non | Nombre maximum de résultats retournés. Défaut et maximum : 100. |
Filtre par date
Lorsque DateDebut et/ou DateFin sont fournis, l’API retourne les codes
liés aux réservations qui chevauchent la période demandée.
Par exemple, une réservation du 2026-07-01 au 2026-07-10 sera retournée
pour une recherche du 2026-07-05 au 2026-07-06.
Source des informations supplémentaires
| Information | Source RéservPro | Détail |
|---|---|---|
| Service | vit_pac |
Le service est retourné dans service.IDService et service.Titre. |
| Site d’une réservation | vit_pac_plan_reserv + vit_pac_plan |
pr_reserv_id pointe vers la réservation et pr_plan_no pointe vers plan_no. |
| Site d’un saisonnier | vit_pac_saisonnier + vit_pac_plan |
saison_idplan pointe vers vit_pac_plan.plan_no. |
| Véhicule | vit_pac_users_veh |
Retourne modèle, couleur, plaque, type, année, vignette et carte d’accès. |
| Conducteur | vit_pac_client_membre |
vps_conducteur pointe vers vpm_id, et le nom est dans vpm_nom. |
Exemple
GET /api/gate-codes?DateDebut=2026-07-01&DateFin=2026-07-31
Authorization: Bearer VOTRE_CLE_API
Exemple avec pagination
GET /api/gate-codes?DateDebut=2026-07-01&DateFin=2026-07-31&Debut=0&Limite=100
Authorization: Bearer VOTRE_CLE_API
Réponse type
{
"success": true,
"error": false,
"endpoint": "gate-codes",
"IDEntreprise": 123,
"data": {
"success": true,
"error": false,
"details": {
"Total": 2,
"Debut": 0,
"Limite": 100,
"DateDebut": "2026-07-01",
"DateFin": "2026-07-31"
},
"codes": [
{
"code": "ABC123",
"type": "reservation",
"reservation": {
"IDReservation": 2786491,
"DateDebut": "2026-07-10",
"DateFin": "2026-07-15",
"Statut": 1,
"Arrivee": -1,
"IDFacture": 1433936
},
"service": {
"IDService": 35197,
"Titre": "Terrain 3 services"
},
"site": {
"IDEmplacement": 8832,
"Nom": "Terrain A-12"
},
"client": {
"IDClient": 789,
"Nom": "Jean Tremblay",
"Email": "jean@example.com",
"Telephone": "514-555-1234"
},
"vehicule": {
"IDVehicule": 321,
"Type": "Automobile",
"Marque": "Toyota",
"Modele": "RAV4",
"Couleur": "Noir",
"Annee": "2020",
"Plaque": "ABC123",
"NoSerie": "",
"Vignette": 1,
"CarteAcces": "ABC123",
"Conducteur": "Marie Tremblay",
"Informations": ""
},
"meta": {
"DateCreation": "2026-07-10 14:32:00",
"DateModification": null,
"Modifie": 0
}
}
]
},
"request_id": "req_exemple"
}
Comportement lorsque le véhicule est absent
Si le code d’accès est lié à une réservation, mais qu’aucun véhicule ne correspond à ce code,
le bloc vehicule est retourné avec des valeurs vides. L’API ne choisit pas automatiquement
un véhicule du client afin d’éviter toute ambiguïté.
"vehicule": {
"IDVehicule": 0,
"Type": "Automobile",
"Marque": "",
"Modele": "",
"Couleur": "",
"Annee": "",
"Plaque": "",
"NoSerie": "",
"Vignette": 0,
"CarteAcces": "",
"Conducteur": "",
"Informations": ""
}
Exemple PHP / cURL
$params = [
'DateDebut' => '2026-07-01',
'DateFin' => '2026-07-31',
'Debut' => 0,
'Limite' => 100
];
$url = 'https://beta.reservpro.com/api/gate-codes?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Authorization: Bearer VOTRE_CLE_API'
],
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (!empty($data['data']['codes'])) {
foreach ($data['data']['codes'] as $row) {
$site = isset($row['site']['Nom']) ? $row['site']['Nom'] : '';
$plaque = isset($row['vehicule']['Plaque']) ? $row['vehicule']['Plaque'] : '';
echo $row['code'] . ' - ' .
$row['reservation']['DateDebut'] . ' - ' .
$site . ' - ' .
$plaque . PHP_EOL;
}
}
Informations ajoutées en bêta
Chaque code de réservation inclut sites et Historique. Le bloc site existant reste présent pour compatibilité; sites couvre les réservations avec plusieurs affectations. L’historique contient les cinq derniers passages enregistrés du code pour cette entreprise. Voir les limites des anciens journaux.
Historique d’un code d’accès
Consulter les passages d’un code, y compris après son expiration ou sa désactivation.
Paramètres
| Paramètre | Règle |
|---|---|
code | Requis. Code exact, 160 octets maximum. |
Limite | 5 passages par défaut; maximum 100. |
Exemple
GET /api/gate-history?code=CODE_EXEMPLE&Limite=5
Authorization: Bearer VOTRE_CLE_BETARéponse
data.Historique contient IDValidation, Date, Type (entree/sortie), IDReservation ou IDSaisonnier. Ordre décroissant par date et identifiant.
{
"success": true,
"error": false,
"endpoint": "gate-history",
"IDEntreprise": 123,
"data": {
"code": "CODE_EXEMPLE",
"FuseauHoraire": "America/Montreal",
"Historique": [
{
"IDValidation": 789,
"Date": "2026-09-08 11:30:00",
"Type": "sortie",
"IDReservation": 456,
"IDSaisonnier": null
}
]
},
"request_id": "req_exemple"
}Limites de l’historique
Seuls les passages dont le code et l’entreprise ont été enregistrés sont retournés. Les anciens logs incomplets ne sont pas reconstruits. Un historique vide ne prouve pas qu’un code n’a jamais été utilisé. Un code réutilisé peut présenter plusieurs réservations.
Voir aussi la validation d’accès et la liste des codes.
Tâches et ménage : fonctionnement
Les opérations utilisent les tâches natives RéservPro. L’application employés et l’API consultent et mettent à jour les mêmes tâches.
https://beta.reservpro.com/api/. Clé de l’entreprise dans Authorization: Bearer. Dates et heures : America/Montreal.Parcours d’intégration
- Consulter les départs du jour et à venir.
- Retrouver les tâches par réservation ou emplacement.
- Commencer ou terminer la tâche par API, ou dans l’application employés.
- Relire l’état effectif de l’emplacement.
Activer un modèle de ménage
Dans les modèles de tâches, choisir « Cette tâche confirme le ménage de l’emplacement ». Les tâches échues todo ou doing rendent l’emplacement non prêt. Les tâches futures à faire ne le bloquent pas aujourd’hui. Une tâche démarrée par anticipation compte immédiatement.
Lire l’état actuel
menage_a_faire: tâche échue ouverte.menage_en_cours: au moins une tâche commencée.pret: confirmation datée et aucune tâche échue ouverte.inconnu: aucune confirmation datée,Pret=null.
Les tâches annulées et les tâches des réservations annulées sont exclues. Les anciennes tâches non terminées restent à faire; elles ne sont jamais complétées automatiquement.
Le ménage décrit la préparation actuelle à accueillir. Il ne bloque pas les réservations futures et ne remplace pas la disponibilité ou l’occupation.
Respecter les règles de tâches
Les modèles requires_report exigent les heures réelles et une note; la note est facultative pour une routine schedule. Les changements par API sont journalisés. Une tâche événementielle peut concerner plusieurs emplacements par sa réservation : sa confirmation affecte alors toutes ces affectations.
Départs du jour et à venir
Retourne les réservations actives dont la date de fin se trouve dans la période choisie, avec leurs emplacements et tâches.
Paramètres
| Paramètre | Règle |
|---|---|
DateDebut / DateFin | Dates YYYY-MM-DD, bornes inclusives. Par défaut : aujourd’hui et J+30. Maximum 366 jours. |
IDService / IDEmplacement | Filtres facultatifs. |
Debut / Limite | Offset et nombre de réservations. Par défaut 0 et 100; maximum 100 par page. |
Exemple
GET /api/departs?DateDebut=2026-09-08&DateFin=2026-09-08
Authorization: Bearer VOTRE_CLE_BETARéponse
data contient DateDebut, DateFin, FuseauHoraire, Total, Debut, Limite et Resultats.
Chaque réservation expose IDReservation, IDService, Service, DateDebut, DateFin, HeureDepart (valeur du dossier), DepartEnregistre, Emplacements et Taches. Les affectations contiennent leurs dates et le bloc Menage actuel. Les tâches incluent IDTache, Etat, IDEmplacement, DebutPrevu et Menage.
Cas particuliers
Les réservations sans code d’accès sont incluses. Sans emplacement, Emplacements est vide et MenageService fournit l’état du service. Un changement d’emplacement intermédiaire figure dans les affectations; il ne constitue pas un départ final.
Pour le suivi du travail, consulter les tâches natives. Ne pas utiliser la liste des codes comme inventaire des départs.
Exemple complet de réponse
Exemple fictif de structure; aucune réservation client réelle n’est reproduite.
{
"success": true,
"error": false,
"endpoint": "departs",
"IDEntreprise": 123,
"data": {
"DateDebut": "2026-09-15",
"DateFin": "2026-09-15",
"FuseauHoraire": "America/Montreal",
"Total": 1,
"Debut": 0,
"Limite": 100,
"Resultats": [
{
"IDReservation": 300,
"IDService": 100,
"Service": "Camping",
"DateDebut": "2026-09-13",
"DateFin": "2026-09-15",
"HeureDepart": "11:00:00",
"DepartEnregistre": false,
"Emplacements": [
{
"IDAffectation": 400,
"IDEmplacement": 200,
"Nom": "Terrain 01",
"DateDebut": "2026-09-13",
"DateFin": "2026-09-15",
"Menage": {
"Statut": "inconnu",
"Libelle": "Ménage non confirmé",
"Pret": null,
"TachesOuvertes": 0,
"IDTaches": [],
"DerniereCompletion": null
}
}
],
"Taches": [
{
"IDTache": 456,
"Etat": "todo",
"IDEmplacement": 200,
"DebutPrevu": "2026-09-15 11:00:00",
"Menage": true
}
],
"MenageService": null
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.DateDebut / DateFin / FuseauHoraire | string | Période du filtre et fuseau des dates/heures. |
data.Total / Debut / Limite | integer | Total filtré, offset et taille de page. |
data.Resultats | array<object> | Départs; [] si aucun. |
IDReservation / IDService | integer | Réservation et service. |
Service / DateDebut / DateFin / HeureDepart | string | null | Libellé et valeurs enregistrées, heure éventuellement vide. |
DepartEnregistre | boolean | Indicateur de départ enregistré. |
Emplacements | array<object> | Affectations, avec IDAffectation et IDEmplacement (integer), Nom, DateDebut, DateFin et Menage. |
Taches | array<object> | Résumé des tâches : IDTache, Etat, IDEmplacement, DebutPrevu et Menage (boolean). Charger /api/taches pour la fiche complète. |
MenageService | object | null | État du service sans unité; null lorsqu’il y a des affectations d’emplacements. |
Consulter et mettre à jour les tâches
Accéder aux tâches natives de l’entreprise, les commencer, les terminer, les rouvrir ou les annuler.
Paramètres
| Paramètre | Règle |
|---|---|
GET : IDTache, IDReservation, IDEmplacement, IDService | Filtres facultatifs. La recherche par emplacement inclut les tâches événementielles liées par réservation. |
GET : Etat / Menage | Etat : todo, doing, done, cancelled. Menage=1 limite aux modèles de ménage. |
GET : DateDebut / DateFin | Facultatives, à fournir ensemble. Filtrent le début prévu. Sans dates : inclut les retards. Maximum 366 jours. |
GET : Debut / Limite | Pagination : 0 et 100 par défaut, 100 maximum. |
PATCH : IDTache, Etat, EtatAttendu | Requis dans le JSON. EtatAttendu est le dernier état lu; un conflit retourne 409. |
PATCH : Rapport, DebutReel, FinReelle | Selon le modèle. Heures au format YYYY-MM-DD HH:MM:SS; rapport de 5000 caractères maximum. |
PATCH : DemarrageAnticipe | Booléen true pour confirmer explicitement une tâche prévue plus tard. |
Exemple
GET /api/taches?Menage=1&Etat=todo
PATCH /api/taches
Content-Type: application/json
Authorization: Bearer VOTRE_CLE_BETA
{"IDTache":456,"Etat":"doing","EtatAttendu":"todo"}Réponse de lecture
data contient Total, Debut, Limite, FuseauHoraire et Resultats. Une tâche expose IDTache, Titre, Etat, IDService, IDEmplacement, IDEmplacements (affectations résolues), IDReservation, IDEmploye, DebutPrevu, FinPrevue, DebutReel, FinReelle, CompleteLe, Description, Menage et ModeCompletion.
Réponse de modification
{
"success": true,
"error": false,
"endpoint": "taches",
"IDEntreprise": 123,
"data": {
"IDTache": 456,
"Etat": "doing",
"DejaApplique": false
},
"request_id": "req_exemple"
}Un réessai vers le même état retourne DejaApplique=true sans deuxième événement. Une tâche annulée ne peut pas être reprise par cette action. Une réouverture remet à zéro sa confirmation; le journal conserve le changement.
Rapports et droits
Les règles sont les mêmes que dans l’application employés : voir le fonctionnement du ménage. Les droits de la clé sont limités à son entreprise. La tâche n’est pas recréée et aucune ancienne tâche n’est complétée implicitement.
Exemple complet de lecture
Exemple fictif de structure, avec identifiants de démonstration. ModeCompletion reprend la valeur configurée du modèle.
{
"success": true,
"error": false,
"endpoint": "taches",
"IDEntreprise": 123,
"data": {
"FuseauHoraire": "America/Montreal",
"Total": 1,
"Debut": 0,
"Limite": 100,
"Resultats": [
{
"IDTache": 456,
"Titre": "Préparer le terrain",
"Etat": "todo",
"IDService": 100,
"IDEmplacement": 200,
"IDEmplacements": [
200
],
"IDReservation": 300,
"IDEmploye": 0,
"DebutPrevu": "2026-09-15 11:00:00",
"FinPrevue": "2026-09-15 12:00:00",
"DebutReel": null,
"FinReelle": null,
"CompleteLe": null,
"Description": "",
"Menage": true,
"ModeCompletion": "requires_report"
}
]
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.Total / Debut / Limite | integer | Total filtré, offset et taille de page. |
data.Resultats | array<object> | Tâches; [] si aucune. |
IDTache / IDService / IDEmplacement / IDReservation / IDEmploye | integer | Identifiants; une association absente peut être représentée par 0. |
IDEmplacements | array<integer> | Affectations d’unités résolues pour la tâche. |
Titre / Description | string | null | Texte configuré. |
Etat | string | todo, doing, done ou cancelled. |
DebutPrevu / FinPrevue / DebutReel / FinReelle / CompleteLe | string | null | Dates/heures natives, généralement YYYY-MM-DD HH:MM:SS. Gérer null et les éventuelles valeurs historiques vides. |
Menage | boolean | Tâche issue d’un modèle de ménage. |
ModeCompletion | string | null | Mode du modèle, utilisé pour les exigences de rapport et d’heures décrites dans la fiche ménage. |
PATCH data.IDTache / Etat / DejaApplique | integer / string / boolean | Tâche modifiée, état obtenu et indication qu’un réessai n’a pas créé un second événement. |
État de ménage d’un emplacement
Lire l’état actuel ou changer la tâche de ménage qui le détermine.
Paramètres
| Paramètre | Règle |
|---|---|
IDEmplacement | Requis pour GET et PATCH. |
PATCH : IDTache | Requis. Tâche d’un modèle de ménage, liée à cet emplacement et à l’entreprise. |
PATCH : Statut | menage_a_faire → todo; menage_en_cours → doing; pret → done. |
PATCH : EtatAttendu | Dernier état natif lu : todo, doing ou done. |
PATCH : Rapport, DebutReel, FinReelle, DemarrageAnticipe | Mêmes règles que PATCH /api/taches. |
Exemple
PATCH /api/emplacement-statut
Content-Type: application/json
Authorization: Bearer VOTRE_CLE_BETA
{
"IDEmplacement": 123, "IDTache": 456,
"Statut": "pret", "EtatAttendu": "doing",
"DebutReel": "2026-09-08 11:00:00",
"FinReelle": "2026-09-08 11:45:00",
"Rapport": "Ménage terminé et vérifié."
}Réponse
data contient IDEmplacement, Nom, Menage, Tache et BloqueReservations=false. Le bloc Menage contient Statut, Libelle, Pret, TachesOuvertes, IDTaches et DerniereCompletion.
Lire l’état effectif
La confirmation d’une tâche peut réussir alors que Menage.Pret=false : d’autres tâches échues restent ouvertes. Toujours lire l’état retourné avant d’afficher « prêt ». Le système n’enregistre pas un second statut indépendant des tâches.
GET /api/emplacements expose également ce bloc. Sans confirmation datée, Pret vaut null. Le ménage n’est pas un blocage commercial des disponibilités futures.
Exemple complet de lecture
Exemple fictif sans confirmation de ménage.
{
"success": true,
"error": false,
"endpoint": "emplacement-statut",
"IDEntreprise": 123,
"data": {
"IDEmplacement": 200,
"Nom": "Terrain 01",
"Menage": {
"Statut": "inconnu",
"Libelle": "Ménage non confirmé",
"Pret": null,
"TachesOuvertes": 0,
"IDTaches": [],
"DerniereCompletion": null
},
"Tache": null,
"BloqueReservations": false
},
"request_id": "req_exemple"
}| Champ | Type JSON | Description |
|---|---|---|
data.IDEmplacement / Nom | integer / string | Unité consultée. |
data.Menage.Statut | string | inconnu, menage_a_faire, menage_en_cours ou pret. |
data.Menage.Libelle | string | Texte d’affichage. |
data.Menage.Pret | boolean | null | true = prêt; false = tâches ouvertes; null = aucune confirmation datée. |
data.Menage.TachesOuvertes / IDTaches | integer / array<integer> | Nombre et identifiants des tâches ouvertes prises en compte. |
data.Menage.DerniereCompletion | string | null | Dernière confirmation datée, ou null. |
data.Tache | object | null | null en GET; résultat de transition (IDTache, Etat, DejaApplique) en PATCH. |
data.BloqueReservations | boolean | false : le ménage ne constitue pas un blocage de vente. |
Application Android employés
L’application RéservPro Employé utilise les mêmes tâches que les endpoints API.
Fonctions disponibles
- Consulter les tâches assignées.
- Commencer et terminer une tâche selon les droits de l’employé.
- Fournir les heures réelles et les rapports requis.
- Accéder aux outils d’entretien et aux échanges d’équipe autorisés.
Essayer en bêta
Télécharger l’application Android bêta Ouvrir le portail employés
Une connexion employé est requise. Version Android bêta 1.0.3-4, Android 7.0 minimum. Le portail est chargé depuis la bêta; les évolutions web du suivi des tâches ne nécessitent pas de nouvelle compilation de l’application.
Choisir le parcours
L’application peut couvrir directement le travail des employés. Les endpoints de tâches servent à connecter un outil externe lorsqu’il est nécessaire.
Exemples PHP / cURL
Fonction GET avec Bearer
function reservpro_api_get($endpoint, $apiKey, $params = []) {
$base = 'https://beta.reservpro.com/api/';
$url = $base . $endpoint . '?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Authorization: Bearer ' . $apiKey
],
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
return ['error' => true, 'message' => curl_error($ch)];
}
curl_close($ch);
return json_decode($response, true);
}
Exemple services
$services = reservpro_api_get('services', 'VOTRE_CLE_API', [
'Service_Publie' => 1,
'Service_Reservable_Public' => 1,
'Debut' => 0,
'Limite' => 20
]);
Fonction POST JSON avec Bearer et idempotence
function reservpro_api_post($endpoint, $apiKey, $payload = [], $idempotencyKey = null) {
$url = 'https://beta.reservpro.com/api/' . $endpoint;
$json = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$headers = [
'Accept: application/json',
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
'Content-Length: ' . strlen($json)
];
if ($idempotencyKey !== null) {
$headers[] = 'Idempotency-Key: ' . $idempotencyKey;
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
return ['error' => true, 'message' => curl_error($ch)];
}
curl_close($ch);
return json_decode($response, true);
}
Exemple disponibilité
$dispo = reservpro_api_post('disponibilite', 'VOTRE_CLE_API', [
'IDService' => 35197,
'Details' => [
'Date_Debut' => '2026-07-10',
'Date_Fin' => '2026-07-15',
'Nbr_Adulte' => 2,
'IDEmplacement' => 8832,
'HeureDebut' => 0,
'HeureDuree' => 0
]
]);
Exemple checkout en PHP
$checkout = reservpro_api_post(
'checkout',
'VOTRE_CLE_API',
[
'IDSession' => 'campingqc_123abc',
'customer' => [
'first_name' => 'Hugo',
'last_name' => 'Girard',
'email' => 'hugo@example.com',
'phone' => '514-555-0199',
'address1' => '123 rue Exemple',
'city' => 'Montréal',
'state' => 'QC',
'country' => 'Canada',
'postal_code' => 'H1H 1H1',
'language' => 'fr'
],
'iframe_origin' => 'https://reservation.partenaire.ca',
'webhook_url' => 'https://reservation.partenaire.ca/webhooks/reservpro',
'webhook_secret' => getenv('RESERVPRO_WEBHOOK_SECRET'),
'partner_reference' => 'CQ-2026-000123',
'metadata' => ['channel' => 'camping-quebec']
],
'cq-commande-20260710-000123'
);
$iframeHtml = $checkout['checkout']['iframe_html'] ?? '';
$checkoutId = $checkout['checkout']['id'] ?? '';
Réponses d’erreur
Les erreurs suivent un format cohérent.
{
"success": false,
"error": true,
"error_code": "invalid_api_key",
"error_message": "Clé API invalide.",
"request_id": "req_…"
}
Erreurs fréquentes
| Code | Message | Cause |
|---|---|---|
| 400 | Paramètre requis manquant | IDService, DateDebut, etc. |
| 401 | Authentification requise | Clé API absente ou invalide. |
| 404 | Introuvable | Route ou ressource non supportée ou inaccessible à ce compte. |
| 405 | Méthode non autorisée | Ex. GET sur /api/gate-access. |
| 410 | Endpoint retiré | Ex. ancienne action confirmer de réservation. |
| 413 | Corps trop volumineux | La limite de 64 Kio est dépassée. |
| 422 | Données invalides | Format de session, origine, client ou autre champ invalide. |
| 429 | Limite atteinte | Quota IP/compte dépassé ou blocage temporaire après de mauvaises clés. |
| 500 | Erreur interne | Réessayer avec la même clé d’idempotence et transmettre le request_id au soutien. |
| 503 | Service indisponible | Le module de checkout n’est pas initialisé ou est temporairement indisponible. |
Notes d’implantation
IDEmplacement dans Details pour vérifier un terrain précis.Recommandation d’architecture
- Utiliser
/api/calendrierpour construire les vues calendrier. - Utiliser
/api/disponibiliteseulement au moment de valider un choix précis. - Conserver la clé API et le secret webhook uniquement côté serveur.
- Conserver
IDSession,IDCheckout,partner_referenceet les clés d’idempotence afin de rapprocher les opérations. - Traiter webhooks et appels de reprise de façon idempotente.
- Utiliser le polling du checkout comme secours et après tout signal provenant de l’iframe.
Activation côté RéservPro
Avant d’ouvrir le checkout aux partenaires, l’exploitant RéservPro doit appliquer la migration datée sql/20260816_partner_api_checkout.sql, définir RESERVPRO_WEBHOOK_ENCRYPTION_KEY dans l’environnement (une valeur Base64 représentant 32 octets est recommandée) et exécuter crontab_api_webhooks.php chaque minute avec cette même variable. Ce worker réconcilie les états, reprend les livraisons interrompues et distribue la file de webhooks. L’endpoint checkout retourne 503 checkout_schema_unavailable tant que la migration n’est pas appliquée et 503 checkout_configuration_unavailable si la clé dédiée est absente ou invalide.
- Configurer le serveur HTTP, le proxy, le CDN et l’outil de suivi pour exclure ou masquer le chemin
/api/payment/rpt_…des journaux d’accès : il contient une capacité temporaire. - Conserver les sorties du worker dans un journal supervisé et alerter sur les livraisons
dead; ne pas rediriger silencieusement toutes les erreurs vers/dev/null. - Fournir la même clé dédiée au processus PHP-FPM et au cron, la sauvegarder hors du dépôt et prévoir une rotation contrôlée avant de remplacer sa valeur.
- Le stockage local des quotas est séparé automatiquement par utilisateur système. Pour imposer un autre emplacement, définir
RESERVPRO_API_RATE_DIRvers un chemin absolu privé, inscriptible par PHP-FPM et protégé en mode0700. - La grâce de libération vaut 900 secondes par défaut.
RESERVPRO_API_CHECKOUT_RELEASE_GRACE_SECONDSpermet de la régler entre 60 et 86 400 secondes; PHP-FPM et le worker doivent recevoir la même valeur. - Un lease interne empêche le worker de libérer un panier pendant une confirmation ou une réponse fournisseur en cours.
RESERVPRO_API_PAYMENT_PROCESSING_LEASE_SECONDSvaut 300 secondes par défaut (60 à 900); le régler au-dessus du délai maximal des passerelles. - Avant la production, tester une interruption immédiatement après un débit et activer un rapprochement durable auprès de chaque fournisseur autorisé. Le webhook envoyé au partenaire confirme l’état RéservPro, mais ne remplace pas la preuve entrante ou la réconciliation de la passerelle de paiement.
Parcours partenaire recommandé
- Obtenir la clé du commerce dans Profil de l’entreprise → Intégration et la conserver côté serveur.
- Lire catégories et services, puis les fiches, attributs et unités nécessaires.
- Consulter le calendrier et demander un calcul précis avec les participants, dates et équipements.
- Créer le panier via /api/reservation avec une IDSession propre au parcours client.
- Créer le checkout avec une clé d’idempotence stable pour la même opération. Le paiement passe par la page hébergée.
- Traiter les webhooks signés et relire le statut du checkout avant de confirmer le paiement. Une fermeture d’iframe ne prouve pas le succès.
Après un délai réseau sur une écriture, ne pas répéter aveuglément une création de réservation. Relire le panier; pour le checkout, réutiliser la même clé d’idempotence et le même corps. Pour les tâches, utiliser EtatAttendu et gérer 409. Une clé API donne accès au compte marchand : le serveur partenaire doit aussi isoler ses propres utilisateurs.
Contrats et exemples vérifiés
Les exemples du catalogue proviennent de lectures HTTP de Démo Camping en bêta au 9 septembre 2026. Les exemples métier fictifs sont signalés. Aucun exemple ne garantit une disponibilité future. Les champs existants sont conservés lors des enrichissements présentés ici; tester les intégrations en bêta avant une mise en production autorisée.