/hotels/{slug}Public · CORS ouvert
Fiche publique de l'hôtel : nom, étoiles, adresse, contact, description en 4 langues, équipements, photos, devise, horaires, URL du moteur et du site.
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
lang | query | non |
Développeurs
Une API REST JSON simple pour afficher les chambres, les prix et les disponibilités d'un hôtel, et créer des réservations directes. Des modules prêts à l'emploi pour WordPress, Joomla et Drupal, et un widget pour toutes les autres plateformes.
URL de basehttps://otelvya.com/api/v1
Les endpoints de réservation exigent une clé d'API, transmise dans l'en-tête Authorization (Bearer) ou X-Api-Key. La clé n'est affichée qu'une fois à sa création ; seule son empreinte est conservée. Elle se garde côté serveur : les endpoints authentifiés n'acceptent pas les appels depuis un navigateur.
Portées : « read » (lecture) et « bookings » (création et consultation des réservations de l'hôtel de la clé). Une clé révoquée cesse immédiatement de fonctionner.
Envoyez un en-tête Idempotency-Key unique avec chaque création : rejouer la même requête (coupure réseau, nouvel essai) renvoie la même réservation au lieu d'en créer une seconde. La même clé avec un corps différent est refusée (409).
Le montant d'une réservation est toujours recalculé par Otelvya. Transmettez expectedTotal (le total affiché au client) : si le prix a changé entre-temps, la réservation est refusée avec price_changed plutôt que facturée à un autre montant.
curl "https://otelvya.com/api/v1/hotels/riad-atlas/availability?checkIn=2026-11-20&checkOut=2026-11-22&adults=2&lang=fr"const res = await fetch(
"https://otelvya.com/api/v1/hotels/riad-atlas/availability?" +
new URLSearchParams({ checkIn: "2026-11-20", checkOut: "2026-11-22", adults: "2", lang: "en" })
);
const data = await res.json();
if (!res.ok) throw new Error(data.error.code + ": " + data.error.message);
for (const o of data.offers) {
console.log(o.room.name, o.meal.label, o.total, o.currency, o.bookingUrl);
}curl -X POST "https://otelvya.com/api/v1/hotels/riad-atlas/bookings" \
-H "Authorization: Bearer $OTELVYA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-000123" \
-d '{
"checkIn": "2026-11-20", "checkOut": "2026-11-22", "adults": 2,
"roomId": "<room.id>", "ratePlanId": "<ratePlan.id>",
"expectedTotal": 245.00,
"guest": { "firstName": "Salma", "lastName": "Bennani",
"email": "salma@example.com", "phone": "+212600000000", "country": "MA" }
}'<?php
$ch = curl_init("https://otelvya.com/api/v1/hotels/riad-atlas/bookings");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("OTELVYA_API_KEY"),
"Content-Type: application/json",
"Idempotency-Key: order-2026-000123",
],
CURLOPT_POSTFIELDS => json_encode([
"checkIn" => "2026-11-20", "checkOut" => "2026-11-22", "adults" => 2,
"roomId" => $roomId, "ratePlanId" => $ratePlanId, "expectedTotal" => 245.00,
"guest" => ["firstName" => "Salma", "lastName" => "Bennani",
"email" => "salma@example.com", "phone" => "+212600000000"],
]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status >= 400) {
throw new RuntimeException($data["error"]["code"] . ": " . $data["error"]["message"]);
}
header("Location: " . ($data["booking"]["payment"]["url"] ?? $data["booking"]["confirmationUrl"]));Comme les interfaces POS et back-office d'OPERA : n'importe quelle caisse, logiciel de facturation, de comptabilité ou de paie peut se brancher dès aujourd'hui sur Otelvya, sans accord partenaire. L'hôtel crée une clé dans Intégrations › Interfaces avec les portées nécessaires.
Portées : « pos » — recherche d'un client en séjour et imputation sur la chambre ; « exports » — factures émises, encaissements et écritures comptables ; « hr » — effectif sans données sensibles. Une clé « read » ou « bookings » ne peut ni imputer ni exporter.
Le client doit être en séjour (arrivée enregistrée) et le module Réception actif pour l'hôtel. Le montant est TTC dans la devise de l'hôtel. La référence externe est unique par point de vente : renvoyer le même ticket ne crée pas de doublon (réponse 200, en-tête Idempotent-Replayed). Refus explicites : 409 not_in_house, folio_closed, module_inactive.
curl "https://otelvya.com/api/v1/hotels/riad-atlas/inhouse?room=101" \
-H "Authorization: Bearer $OTELVYA_API_KEY"curl -X POST "https://otelvya.com/api/v1/hotels/riad-atlas/folio-charges" \
-H "Authorization: Bearer $OTELVYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"room": "101",
"amount": 185.50, "taxRate": 10,
"label": "Ticket 4512 — dîner 2 couverts",
"reference": "T-4512", "outlet": "Restaurant"
}'curl -X POST "https://otelvya.com/api/v1/hotels/riad-atlas/folio-charges/<charge.id>/void" \
-H "Authorization: Bearer $OTELVYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Ticket saisi sur la mauvaise chambre" }'Formats JSON (défaut) ou CSV (format=csv, UTF-8, séparateur virgule). Période de 366 jours au plus, 5 000 lignes au plus (en-tête X-Export-Truncated au-delà). Les écritures exigent le module Comptabilité, l'effectif le module RH ; l'effectif n'expose jamais le RIB, la CIN, le n° de sécurité sociale ni la situation familiale.
curl "https://otelvya.com/api/v1/hotels/riad-atlas/exports/invoices?from=2026-10-01&to=2026-10-31&format=csv" \
-H "Authorization: Bearer $OTELVYA_API_KEY" -o factures.csvcurl "https://otelvya.com/api/v1/hotels/riad-atlas/exports/journal?from=2026-10-01&to=2026-10-31&format=csv" \
-H "Authorization: Bearer $OTELVYA_API_KEY" -o ecritures.csvcurl "https://otelvya.com/api/v1/hotels/riad-atlas/exports/employees?format=csv" \
-H "Authorization: Bearer $OTELVYA_API_KEY" -o effectif.csvPas de webhooks sortants pour l'instant : les logiciels interrogent l'API (par exemple chaque nuit pour les exports). L'envoi d'événements signés (imputation, facture émise) est une évolution prévue.
Description complète au format OpenAPI 3.1, à importer dans Postman, Insomnia ou un générateur de client : /api/v1/openapi.json
/hotels/{slug}Public · CORS ouvert
Fiche publique de l'hôtel : nom, étoiles, adresse, contact, description en 4 langues, équipements, photos, devise, horaires, URL du moteur et du site.
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
lang | query | non |
/hotels/{slug}/roomsPublic · CORS ouvert
Types de chambres avec photos, capacité, équipements et prix « à partir de » sur les 30 prochaines nuits.
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
lang | query | non |
/hotels/{slug}/availabilityPublic · CORS ouvert
Offres vendables pour un séjour : total et prix par nuit, pension, conditions d'annulation, chambres restantes (plafonné à 3) et lien de réservation pré-rempli.
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
checkIn | query | oui |
checkOut | query | oui |
adults | query | non |
children | query | non |
promo | query | non |
currency | query | non |
lang | query | non |
/hotels/{slug}/calendarPublic · CORS ouvert
Prix minimum et disponibilité pour chaque nuit (60 nuits au plus).
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
from | query | non |
days | query | non |
/hotels/{slug}/bookingsClé d'API requise
Crée une réservation avec les mêmes contrôles que le moteur public ; renvoie le code, le lien de confirmation et, si l'hôtel l'a activé, le lien de paiement en ligne.
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
Idempotency-Key | header | non |
/hotels/{slug}/inhouseClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
room | query | non |
folio | query | non |
name | query | non |
/hotels/{slug}/folio-chargesClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
/hotels/{slug}/folio-charges/{id}/voidClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
id | path | oui |
/hotels/{slug}/exports/invoicesClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
from | query | oui |
to | query | oui |
format | query | non |
/hotels/{slug}/exports/paymentsClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
from | query | oui |
to | query | oui |
format | query | non |
/hotels/{slug}/exports/journalClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
from | query | oui |
to | query | oui |
format | query | non |
/hotels/{slug}/exports/employeesClé d'API requise
| Paramètre | Emplacement | Requis |
|---|---|---|
slug | path | oui |
format | query | non |
/bookings/{code}Clé d'API requise
Consulte une réservation de l'hôtel de la clé (statut, montants, paiement).
| Paramètre | Emplacement | Requis |
|---|---|---|
code | path | oui |
lang | query | non |
Toutes les erreurs ont la même forme, avec un code stable à tester dans votre code et un message lisible :
{ "error": { "code": "invalid_dates", "message": "La date d'arrivée est passée." } }Si le moteur de réservation d'un hôtel est hors ligne (abonnement) ou si la plateforme est en maintenance, l'API répond 503 avec un code explicite ; un hôtel inconnu répond 404. Aucune donnée interne n'est jamais exposée.
Codes courts, bloc Gutenberg, widget, cache de 5 minutes, traductions fr/en/es/ar. PHP 7.4+.
TéléchargerModule de site pour Joomla 4 et 5 : recherche, chambres avec prix ou bouton, 4 langues.
TéléchargerWix, Squarespace, Webflow, Shopify, Google Sites, HTML : collez le code d'intégration généré dans Otelvya (recherche, bouton ou liste des chambres).
Une question technique ? Écrivez-nous depuis la page de contact.