Gestion des tarifs
Les endpoints de catalogue et d'offres sont en lecture seule. Ceux-ci permettent à une intégration de gérer la structure tarifaire : créer des tarifs, superposer une tarification saisonnière, regrouper des prestations incluses et des crédits, et animer des promotions avec des codes. C'est ainsi qu'un hôtel pilote ses prix Veridien depuis son propre site ou son back-office.
Tous les endpoints de cette page exigent la portée rates:write, sauf les lectures de gestion (GET), qui exigent rates:read.
Une promotion est un tarif
Une promotion est un tarif avec kind: "promotion" et une dérivation depuis un
tarif de base. Il n'y a pas d'endpoint de promotion distinct : vous en créez et en
modifiez une par les mêmes endpoints /rate-plans, en réglant kind,
derived_from_id, derivation_type et derivation_value.
Idempotence
Chaque écriture de cette page est une requête qui modifie des données. Envoyez un
en-tête Idempotency-Key pour rendre les nouvelles tentatives sûres, comme décrit
dans Conventions.
POST /rate-plans| Champ | Requis | Notes |
|---|---|---|
room_type_id | oui | Le type de chambre que ce tarif tarife. |
name | oui | Nom interne (1 à 100 caractères). |
base_price | oui | Prix par nuit, en chaîne décimale, par exemple "120.00". |
currency | non | Doit être la devise de base de l'établissement ou une devise configurée. Par défaut, la devise de base. |
public_name | non | Nom montré au client. |
description | non | Texte de présentation montré au client. |
image_url | non | URL absolue. |
extra_guest_charge | non | Frais par nuit et par client au-delà de l'occupation de base. "0.00" par défaut. |
single_guest_discount | non | "0.00" par défaut. |
single_guest_discount_type | non | fixed ou percent. fixed par défaut. |
min_los / max_los | non | Bornes de durée de séjour, en nuits. |
booking_window_start / _end | non | Quand le tarif peut être réservé (YYYY-MM-DD). |
stay_window_start / _end | non | Quand le séjour peut avoir lieu sur ce tarif. |
active_for_booking_engine | non | false par défaut. |
active_for_channels | non | false par défaut. |
kind | non | standard (par défaut) ou promotion. |
derived_from_id | non | Pour une promotion : le tarif de base dont elle dérive. |
derivation_type | non | percent, fixed ou perPerson. Requis avec derived_from_id. |
derivation_value | non | Chaîne décimale signée. Une valeur négative est une remise, par exemple "-20.00". Requis avec derived_from_id. |
curl -X POST "$VRDN_BASE/rate-plans" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"name": "Bed & Breakfast",
"base_price": "120.00",
"public_name": "Bed & Breakfast",
"description": "A full breakfast for two each morning.",
"active_for_booking_engine": true
}'{ "rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02" }Réglez kind, le parent et une dérivation négative. Pour la réserver à un code, ajoutez-en un (voyez plus bas) et réglez requires_promo_code: true.
curl -X POST "$VRDN_BASE/rate-plans" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"name": "Advance Purchase, save 20%",
"base_price": "120.00",
"kind": "promotion",
"derived_from_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
"derivation_type": "percent",
"derivation_value": "-20.00",
"active_for_booking_engine": true
}'Un tarif dérivé exige à la fois derivation_type et derivation_value, sans quoi la requête est rejetée. Son prix est toujours le prix courant du parent auquel la dérivation est appliquée, il suit donc automatiquement la tarification saisonnière du parent.
PATCH /rate-plans/{id}N'envoyez que les champs que vous voulez changer. Accepte les mêmes champs que la création (sauf room_type_id), plus is_active.
{ "rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02", "updated": true }DELETE /rate-plans/{id}Le tarif par défaut ne peut pas être supprimé (403). Les réservations déjà faites sur un tarif supprimé conservent le prix qui leur a été annoncé.
{ "rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02", "deleted": true }Les périodes superposent une tarification et des règles de séjour propres à certaines dates au prix de base d'un tarif. Les périodes d'un même tarif ne doivent pas se chevaucher ; une plage qui en chevauche une autre renvoie 409.
GET /rate-plans/{id}/intervalsExige rates:read.
POST /rate-plans/{id}/intervals| Champ | Requis | Notes |
|---|---|---|
name | oui | Par exemple « Haute saison ». |
start_date / end_date | oui | YYYY-MM-DD. La date de début doit précéder la date de fin. |
price_mon … price_sun | non | Prix par jour de la semaine. Un jour laissé vide retombe sur le prix de base. |
min_stay / max_stay | non | Règles de durée de séjour pour cette plage. |
closed_to_arrival / closed_to_departure / stop_sell | non | Indicateurs de disponibilité. false par défaut. |
extra_guest_charge / single_guest_discount | non | Valeurs propres à la saison. "0.00" par défaut. |
curl -X POST "$VRDN_BASE/rate-plans/5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02/intervals" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "High Season",
"start_date": "2026-12-01",
"end_date": "2027-03-31",
"price_mon": "180.00", "price_fri": "210.00",
"min_stay": 3
}'{ "interval_id": "d8a4c2f6-5e9b-4d7a-8f1c-3b6e0a9d5c28" }PATCH /intervals/{id}
DELETE /intervals/{id}PATCH accepte n'importe quel champ de période et revérifie la règle de non-chevauchement.
Une prestation incluse est soit un avantage (un élément inclus fixe), soit un crédit (une enveloppe dépensable sur une catégorie, comme un crédit spa). Les prestations incluses se définissent en bloc : un POST remplace tout l'ensemble des prestations du tarif.
GET /rate-plans/{id}/inclusionsExige rates:read.
POST /rate-plans/{id}/inclusions| Champ | Requis | Notes |
|---|---|---|
label | oui | Libellé montré au client, par exemple « Crédit spa ». |
allocated_amount | oui | Valeur en chaîne décimale. "0.00" pour un avantage gratuit. |
frequency | oui | perStay, perNight, perGuest ou perGuestPerNight. |
inclusion_kind | non | perk (par défaut) ou credit. |
revenue_category | oui | room, fnb, spa, excursions, activities ou other. Pour un crédit, c'est la catégorie sur laquelle il s'applique. |
service_item_id | non | Lien vers un article de service du catalogue. |
currency | non | Par défaut, la devise du tarif. |
included_quantity | non | 1 par défaut. |
curl -X POST "$VRDN_BASE/rate-plans/5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02/inclusions" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{
"inclusions": [
{ "label": "Daily breakfast for two", "allocated_amount": "20.00", "frequency": "perGuestPerNight", "revenue_category": "fnb" },
{ "label": "Spa credit", "allocated_amount": "150.00", "frequency": "perStay", "inclusion_kind": "credit", "revenue_category": "spa" }
]
}'{ "rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02", "count": 2 }Un code débloque une promotion. La remise vit dans la promotion, un code ne porte donc jamais d'économie propre. Rattachez les codes au tarif qu'ils débloquent.
GET /rate-plans/{id}/promo-codesExige rates:read.
POST /rate-plans/{id}/promo-codes| Champ | Requis | Notes |
|---|---|---|
code | oui | 3 à 40 caractères. Stocké et comparé en majuscules. |
valid_from / valid_to | non | Fenêtre au format YYYY-MM-DD. |
max_redemptions | non | Plafond d'utilisations au total. Omettez-le pour un nombre illimité. |
max_per_guest | non | Plafond par client. |
curl -X POST "$VRDN_BASE/rate-plans/e2a9d7c4-3f6b-4c1e-9a8d-7b5f0c2e4a19/promo-codes" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "code": "EARLYBIRD25", "max_redemptions": 100 }'{ "promo_code_id": "a5e2c8f1-7d4b-4a6e-b9c3-0f8d2a5e7c41", "code": "EARLYBIRD25" }PATCH /promo-codes/{id}
DELETE /promo-codes/{id}PATCH accepte valid_from, valid_to, max_redemptions, max_per_guest et is_active. La chaîne du code elle-même ne peut pas être modifiée, car les réservations figent le code avec lequel elles ont été faites ; supprimez-le et créez-en un nouveau à la place. Supprimer un code n'affecte pas les réservations déjà faites avec lui.