Flux de réservation
Endpoints orientés consommateur pour la réservation de rendez-vous. Ces endpoints sont également utilisés par le widget BookingJS et sont optimisés pour les intégrations frontend.
Aucune authentification requise
Aperçu
Le flux de réservation standard se compose de trois étapes :
- Récupérer les rendez-vous disponibles - liste de tous les créneaux réservables
- Réserver un rendez-vous - blocage de 3 minutes sur le créneau sélectionné
- Finaliser la réservation - finaliser le rendez-vous avec les données du consommateur
| Méthode | Endpoint | Description |
|---|---|---|
GET | /resources/:ref/upcoming_bookables | Récupérer les rendez-vous disponibles |
POST | /rest/1/resources/:ref/reserve_appointment | Réserver un rendez-vous (3 min) |
POST | /resources/:ref/create_appointment_with_consumer | Finaliser la réservation |
POST | /products/active_products | Récupérer les produits actifs |
POST | /resources/public_data | Données publiques des ressources |
OPTIONS | /resources/:ref/upcoming_bookables | Preflight CORS |
1. Récupérer les rendez-vous disponibles
Récupère tous les créneaux réservables pour une ou plusieurs ressources. Les résultats sont regroupés selon un format de date configurable, afin de faciliter une UI à deux niveaux (par ex. vue mensuelle → liste journalière).
GET /resources/{ref}/upcoming_bookables
Paramètres de chemin
| Paramètre | Type | Description |
|---|---|---|
ref | string | Référence de ressource ou UUID. Formats : resourceId@providerUuid@platform - référence complète ; resourceId@platform - forme courte ; uuid - UUID direct de la ressource |
Paramètres de requête
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
groupFormat | string | Non | Format Joda-Time pour le regroupement. Tous les bookables ayant la même valeur se retrouvent dans un même groupe. Par défaut : yyyy-MM-dd. Exemples : MM-yyyy (mensuel), MMMM (nom du mois) |
timeFormat | string | Non | Format pour formattedStart/formattedEnd. Par défaut : yyyy-MM-dd HH:mm |
languageTag | string | Non | Balise de langue IETF BCP 47 pour la traduction côté serveur (par ex. noms de mois). Exemple : de_DE, fr_FR |
channelKey | string | Non | Canal de réservation. Par défaut : RESOURCE_PUBLIC. Voir Channel Keys |
ref | string | Non | Références de ressource supplémentaires. Peut être spécifié plusieurs fois pour charger les bookables de plusieurs ressources simultanément |
prdRef | string | Non | Référence de produit ou UUID. Filtre sur les bookables qui prennent en charge ce produit. Tient également compte du leadTime/followUpTime du produit |
Request
curl -X GET "https://www.timum.de/resources/my-resource@myPlatform/upcoming_bookables?groupFormat=MMMM&languageTag=fr_FR"
Response
La réponse est un objet avec des clés dynamiques basées sur le groupFormat. Elle contient également un indicateur public_visible.
{
"avril 18": [
{
"formattedStart": "2018-04-30 14:00",
"formattedEnd": "2018-04-30 14:30",
"start": "2018-04-30T14:00:00+02:00",
"end": "2018-04-30T14:30:00+02:00",
"timeslot_uuid": "6cb6df60-48d8-11e8-a5e5-263fa1a58213",
"product_uuid": "7fc85970-a2d0-11e2-9cd0-1231430706c1",
"resource_uuid": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"product_name": "Gesellschaftsspiele spielen",
"resource_name": "2nd Level Support",
"contact_channel": null,
"capacity": 1,
"capacity_left": 1,
"products": [],
"kind": "models.Bookable"
}
],
"mai 18": [
{
"appointment_uuid": "864b80c0-483f-11f0-b6e3-72fe2304273f",
"formattedStart": "2018-05-02 14:00",
"formattedEnd": "2018-05-02 14:30",
"start": "2018-05-02T14:00:00+02:00",
"end": "2018-05-02T14:30:00+02:00",
"timeslot_uuid": "267b2d70-48d9-11e8-a5e5-263fa1a58213",
"product_uuid": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22",
"resource_uuid": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"product_name": "Video Call 30",
"resource_name": "2nd Level Support",
"contact_channel": {
"type": "location",
"value": "Telefon und Bildschirmfreigabe (wir rufen Sie an)"
},
"capacity": 5,
"capacity_left": 3,
"products": [
{ "uuid": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22", "name": "Video Call 30" }
],
"kind": "models.LotAppointment"
}
],
"public_visible": true
}
Types de Bookable
| kind | Signification | Particularité |
|---|---|---|
models.Bookable | Créneau issu d'une disponibilité (timeslot) | Devient un LotAppointment lors de la première réservation. Utilisez timeslot_uuid pour reserve/create |
models.LotAppointment | Rendez-vous en groupe existant avec capacité restante | Rendez-vous déjà créé. Utilisez appointment_uuid pour reserve/create |
Bookable vs LotAppointment
models.Bookable est un créneau potentiel issu d'une disponibilité. Dès que le premier consommateur réserve, il devient un models.LotAppointment avec un nouveau appointment_uuid. Pour les réservations suivantes du même créneau, vous devez utiliser ce nouvel UUID !Champs de la réponse
| Champ | Type | Description |
|---|---|---|
start / end | string | Horodatage ISO 8601 avec fuseau horaire |
formattedStart / formattedEnd | string | Heure formatée selon timeFormat |
timeslot_uuid | string | UUID de la disponibilité sous-jacente |
appointment_uuid | string? | UUID du rendez-vous (uniquement pour LotAppointment) |
product_uuid | string? | UUID du produit, ou null |
resource_uuid | string | UUID de la ressource |
capacity | number | Capacité totale du créneau |
capacity_left | number | Places restantes |
contact_channel | object? | Canal de contact avec type et value |
products | array | Liste des produits disponibles pour ce créneau |
kind | string | models.Bookable ou models.LotAppointment |
Codes de statut
| Code | Signification |
|---|---|
200 | Succès, bookables retournés |
204 | Aucun bookable disponible (réponse vide) |
2. Réserver un rendez-vous
Réserve temporairement un rendez-vous pendant 3 minutes. Pendant ce délai, le créneau ne peut être réservé que par le client à l'origine de la réservation. Cela évite les doubles réservations pendant la saisie du formulaire.
POST /rest/1/resources/{ref}/reserve_appointment
Toujours appeler avant de réserver
create_appointment_with_consumer ! Même après l'expiration des 3 minutes, vous pouvez encore finaliser la réservation - mais si un autre client a été plus rapide, elle échouera.Paramètres de requête
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
ref | string | Non | Référence de ressource ou de canal |
channelKey | string | Non | Canal de réservation. Par défaut : RESOURCE_PUBLIC |
Request Body
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
timeslot_uuid | string | Conditionnel* | UUID du timeslot (disponibilité). À utiliser pour models.Bookable. Applique les paramètres par défaut de la disponibilité au nouveau rendez-vous |
appointment_uuid | string | Conditionnel* | UUID du rendez-vous existant. Obligatoire pour models.LotAppointment |
product_uuid | string | Oui | UUID du produit à réserver |
from | string | Oui | Heure de début du bookable (ISO 8601, UTC) |
to | string | Oui | Heure de fin du bookable (ISO 8601, UTC) |
* Pour models.Bookable, envoyez timeslot_uuid. Pour models.LotAppointment, appointment_uuid est obligatoire.
Request
curl -X POST "https://www.timum.de/rest/1/resources/my-resource@myPlatform/reserve_appointment" \
-H "Content-Type: application/json" \
-d '{
"timeslot_uuid": "6cb6df60-48d8-11e8-a5e5-263fa1a58213",
"product_uuid": "7fc85970-a2d0-11e2-9cd0-1231430706c1",
"from": "2025-01-15T13:00:00Z",
"to": "2025-01-15T13:30:00Z"
}'
Response
{
"api-info": { "version": "1" },
"participation": {
"uuid": "a48dcf00-483c-11f0-b6e3-72fe2304273f",
"appointment_uuid": "a48d0bb0-483c-11f0-b6e3-72fe2304273f",
"timeslot_uuid": "a48e6b40-483c-11f0-b6e3-72fe2304273f",
"resource_uuid": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"product_uuid": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22",
"from": "2025-06-16T12:25:00Z",
"to": "2025-06-16T12:55:00Z",
"appointment_capacity": 1,
"appointment_capacity_left": 0,
"customer_uuid": "a48df610-483c-11f0-b6e3-72fe2304273f",
"customer_mobile": null,
"customer_fullName": null,
"customer_email": null,
"customer_note": null,
"state": "RESERVED",
"formatedAddress": "Telefon und Bildschirmfreigabe (wir rufen Sie an)",
"messages": []
},
"appointments": [
{
"uuid": "a48d0bb0-483c-11f0-b6e3-72fe2304273f",
"kind": "models.LotAppointment",
"product_id": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22",
"product_name": "Video Call 30",
"resource_id": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"from": "2025-06-16T12:25:00Z",
"to": "2025-06-16T12:55:00Z",
"state": "ACTIVE",
"capacity": 1,
"capacity_left": 0,
"customers": [
{
"customer_placeholder_id": "a48df610-483c-11f0-b6e3-72fe2304273f",
"customer_uuid": "a48df610-483c-11f0-b6e3-72fe2304273f",
"participationState": "RESERVED",
"participation_id": "a48dcf00-483c-11f0-b6e3-72fe2304273f"
}
]
}
]
}
Enregistrer customer_uuid
participation.customer_uuid à partir de la réponse ! Vous aurez besoin de cette valeur comme placeholder_id pour l'appel à create_appointment_with_consumer.Comportement de la réservation
- La réservation est valable pendant 3 minutes
- Le
stateestRESERVED - Une fois le délai expiré, la réservation est automatiquement supprimée
capacity_leftest réduit pendant la réservation- Vous pouvez encore réserver après le délai - mais sans protection contre les doubles réservations
3. Finaliser la réservation
Finalise la réservation avec les données du consommateur. Si un utilisateur existe déjà avec l'email ou le numéro de téléphone indiqué, le rendez-vous est rattaché à ce compte. Sinon, un nouveau compte est créé.
POST /resources/{ref}/create_appointment_with_consumer
Paramètres de requête
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
timeFormat | string | Non | Format des indications de temps dans la réponse |
Request Body
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
start | string | Oui | Heure de début (ISO 8601) |
end | string | Oui | Heure de fin (ISO 8601) |
timeslot_uuid | string | Oui | UUID du timeslot ou du rendez-vous |
product_uuid | string | Non | UUID du produit |
placeholder_id | string | Non* | participation.customer_uuid issu de la réponse de réservation. Identifie la réservation |
email | string | Oui | Email du consommateur |
firstname | string | Oui | Prénom du consommateur |
lastname | string | Oui | Nom du consommateur |
mobile | string | Non | Numéro de mobile du consommateur |
message | string | Non | Message facultatif (max. 1024 caractères) |
locale | string | Non | Code de langue (par ex. de, en). Détermine la langue des emails transactionnels |
channelKey | string | Non | Canal de réservation. Par défaut : RESOURCE_PUBLIC |
* placeholder_id est techniquement facultatif, mais vous devriez toujours l'envoyer pour garantir que la réservation de votre utilisateur est utilisée.
Request
curl -X POST "https://www.timum.de/resources/my-resource@myPlatform/create_appointment_with_consumer" \
-H "Content-Type: application/json" \
-d '{
"start": "2025-01-15T13:00:00Z",
"end": "2025-01-15T13:30:00Z",
"timeslot_uuid": "6cb6df60-48d8-11e8-a5e5-263fa1a58213",
"product_uuid": "7fc85970-a2d0-11e2-9cd0-1231430706c1",
"placeholder_id": "a48df610-483c-11f0-b6e3-72fe2304273f",
"channelKey": "RESOURCE_PUBLIC",
"email": "max@example.com",
"firstname": "Max",
"lastname": "Mustermann",
"mobile": "0173 1234567",
"locale": "de",
"message": "Ich freue mich auf den Termin."
}'
Response (Succès)
{
"api-info": { "version": "1" },
"createdAppointment": {
"appointment_uuid": "864b80c0-483f-11f0-b6e3-72fe2304273f",
"start": "2025-06-17T11:05:00+02:00",
"end": "2025-06-17T12:05:00+02:00",
"timeslot_uuid": "864c4410-483f-11f0-b6e3-72fe2304273f",
"product_uuid": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22",
"resource_uuid": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"contact_channel": {
"type": "location",
"value": "Telefon und Bildschirmfreigabe (wir rufen Sie an)"
},
"product_name": "Video Call 30",
"resource_name": "2nd Level Support",
"capacity": 1,
"capacity_left": 0,
"products": [
{ "uuid": "0bd09a60-1d8f-11e9-bf75-06ecf2a1ba22", "name": "Video Call 30" }
],
"kind": "models.LotAppointment",
"cancelLink": "https://www.timum.de/rebook/6366c430-006c-11ec-a5c8-02e4d9518b64?..."
}
}
cancelLink
cancelLink. Ce lien signé permet au consommateur d'annuler son rendez-vous de manière autonome. Vous pouvez utiliser ce lien dans votre email de confirmation.Response (Erreur)
{
"api-info": { "version": "1" },
"errors": [
{
"errorCode": "201",
"message": "Das überlappt mit einem anderen Termin."
}
]
}
Détails de l'algorithme
- Si un utilisateur existe déjà avec l'email ou le numéro de mobile, le rendez-vous est rattaché à ce compte
- Les attributs manquants (firstname, lastname, mobile) sont complétés chez l'utilisateur existant, mais jamais écrasés
- La langue du nouvel utilisateur est reprise de l'acteur CRM (ou via le paramètre
locale) - Pour les rendez-vous en groupe : la première réservation crée le rendez-vous, les suivantes augmentent le nombre de participants
Codes de statut
| Code | Signification |
|---|---|
201 | Rendez-vous créé avec succès |
400 | Champ obligatoire manquant ou invalide |
412 | Créneau déjà réservé (errorCode 201) |
Dépannage
| Problème | Cause | Solution |
|---|---|---|
| "Das überlappt mit einem anderen Termin" (errorCode 201) | Créneau d'une disponibilité déjà réservé. La première réservation génère un nouveau rendez-vous avec un nouvel UUID | Utilisez le nouveau timeslot_uuid issu de la première réponse de réservation pour les réservations suivantes |
| "Email manquant" alors qu'il est présent dans le body | Problème de redirection dû à l'absence de www. | Assurez-vous d'utiliser https://www.timum.de (avec www.) |
| Redirection 301 sans réponse | www. manquant dans l'URL | Utilisez toujours https://www.timum.de |
| AppointmentAlreadyBookedException | Le consommateur participe déjà à ce rendez-vous | Un utilisateur ne peut pas participer deux fois au même rendez-vous. Vérifiez l'absence de doublons |
4. Récupérer les produits actifs
Récupère tous les produits actifs/activés d'une ressource. La liste de résultats peut être filtrée selon les paramètres de canal.
POST /products/active_products
Paramètres de requête
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
ref | string | Conditionnel* | Référence de ressource ou de canal. Peut être spécifié plusieurs fois |
tslRefs | string | Conditionnel* | Référence de rendez-vous ou de disponibilité. Peut être spécifié plusieurs fois |
channelKey | string | Non | Canal de réservation. Par défaut : RESOURCE_PUBLIC |
* Au moins ref ou tslRefs doit être spécifié.
Request
curl -X POST "https://www.timum.de/products/active_products?ref=my-resource@myPlatform&channelKey=RESOURCE_PUBLIC"
Response
{
"products": [
{
"uuid": "92867f70-4836-11e5-bc04-021a52c25043",
"name": "Besichtigung",
"description": "",
"minDuration": 30,
"maxDuration": 45,
"leadTimeMinutes": 0,
"followUpTimeMinutes": 20,
"exclusive": false
},
{
"uuid": "0bb978c0-5740-11eb-8b95-024759471364",
"name": "Beratungsgespräch",
"description": "Ausführliches Beratungsgespräch",
"minDuration": 60,
"maxDuration": 90,
"leadTimeMinutes": null,
"followUpTimeMinutes": null,
"exclusive": true
}
]
}
Champs de la réponse
| Champ | Type | Description |
|---|---|---|
uuid | string | ID unique du produit |
name | string | Nom d'affichage du produit |
description | string | Description du produit (pour les notes clients) |
minDuration | number? | Durée minimale en minutes |
maxDuration | number? | Durée maximale en minutes |
leadTimeMinutes | number? | Délai en amont (trajet/préparation) en minutes |
followUpTimeMinutes | number? | Délai en aval (retour/clôture) en minutes |
exclusive | boolean | Indique si le produit est exclusif (uniquement pour certains canaux) |
5. Récupérer les données publiques
Récupère des informations publiques sur le provider, la ressource, les paramètres de canal et la personne de contact. Utile pour l'affichage des widgets de réservation.
POST /resources/public_data
Paramètres de requête
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
ref | string | Conditionnel* | Référence de ressource ou de canal. Peut être spécifié plusieurs fois |
tslRefs | string | Conditionnel* | Référence de rendez-vous ou de disponibilité. Peut être spécifié plusieurs fois |
channelKey | string | Non | Canal de réservation. Par défaut : RESOURCE_PUBLIC |
* Au moins ref ou tslRefs doit être spécifié.
Request
curl -X POST "https://www.timum.de/resources/public_data?ref=my-resource@myPlatform&channelKey=RESOURCE_PUBLIC"
Response
{
"contact": {
"name": "Max Makler",
"email": "kontakt@example.de",
"mobile": "0173 1234567",
"phone": "030 12345678"
},
"resource": {
"uuid": "636627f0-006c-11ec-a5c8-02e4d9518b64",
"name": "Musterstraße 1",
"description": "Schöne 3-Zimmer-Wohnung mit Balkon",
"contactChannelType": "",
"msgHelpText": "",
"url": "https://example.com/expose/123",
"imgUrl": "https://cdn.example.com/images/123.jpg"
},
"provider": {
"name": "Mustermakler GmbH",
"description": "Ihr Partner für Immobilien in Berlin",
"isThemingAllowed": true,
"isLocalisationAllowed": true,
"areCustomFieldsAllowed": true
},
"channel": {
"bookingProcess": "IMMEDIATE"
}
}
Structure de la réponse
contact
| Champ | Description |
|---|---|
name | Nom de la personne de contact (issu du contact profile) |
email | Adresse email publique |
mobile | Numéro de mobile |
phone | Numéro de ligne fixe |
resource
| Champ | Description |
|---|---|
uuid | ID unique de la ressource |
name | Nom public de la ressource |
description | Description de la ressource |
url | URL externe (par ex. lien vers l'annonce immobilière) |
imgUrl | URL de l'image de la ressource |
provider
| Champ | Description |
|---|---|
name | Nom du calendrier/de l'entreprise |
description | Description du provider |
isThemingAllowed | Indique si le theming personnalisé est autorisé |
isLocalisationAllowed | Indique si la localisation personnalisée est autorisée |
areCustomFieldsAllowed | Indique si les champs personnalisés sont autorisés |
channel
| Champ | Description |
|---|---|
bookingProcess | IMMEDIATE = réservation directe, REQUESTED = demande de rendez-vous |
6. Preflight CORS
Les navigateurs envoient automatiquement des requêtes OPTIONS avant les requêtes cross-origin. timum y répond automatiquement pour tous les endpoints de réservation consommateur.
OPTIONS /resources/{ref}/upcoming_bookables
Response Headers
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Auth-Token
Access-Control-Max-Age: 36
Support CORS automatique
Channel Keys
timum prend en charge 4 canaux de réservation différents. Chaque canal dispose de ses propres paramètres pour la visibilité, le processus de réservation et le filtrage des produits.
| channelKey | Nom (UI) | Utilisation |
|---|---|---|
RESOURCE_PUBLIC | Lien de réservation public | Canal par défaut. Peut être publié publiquement |
RESOURCE_EXCLUSIVE | Accès de réservation exclusif | Pour les clients acceptés (carnet d'adresses) |
RESOURCE_REFERENCE | Calendrier de réservation intégré | Pour les embeds générés automatiquement (par ex. portails immobiliers) |
CALENDAR_PUBLIC | Plugin de site web & calendrier global | Pour les plugins de site web avec toutes les ressources |
Les paramètres de canal peuvent être configurés dans le frontend timum sous Ressource → Activer la réservation de rendez-vous.
Processus de réservation
| Processus | Description |
|---|---|
IMMEDIATE | Réservation directe. Le rendez-vous est confirmé immédiatement. Le consommateur reçoit une confirmation, le provider reçoit une notification |
REQUESTED | Demande de rendez-vous. Le rendez-vous doit être confirmé par le provider. Le consommateur reçoit "Demande reçue", le provider reçoit la demande à confirmer |
Flux de réservation complet
Voici le déroulement complet pour la réservation d'un rendez-vous :
Étape 1 : Charger les bookables
curl "https://www.timum.de/resources/immobilie-123@is24/upcoming_bookables?groupFormat=yyyy-MM-dd&prdRef=besichtigung-30min@is24"
Étape 2 : Réserver le créneau
curl -X POST "https://www.timum.de/rest/1/resources/immobilie-123@is24/reserve_appointment" \
-H "Content-Type: application/json" \
-d '{
"timeslot_uuid": "6cb6df60-48d8-11e8-a5e5-263fa1a58213",
"product_uuid": "7fc85970-a2d0-11e2-9cd0-1231430706c1",
"from": "2025-01-15T14:00:00Z",
"to": "2025-01-15T14:30:00Z"
}'
# La réponse contient participation.customer_uuid -> à conserver !
Étape 3 : Finaliser la réservation
curl -X POST "https://www.timum.de/resources/immobilie-123@is24/create_appointment_with_consumer" \
-H "Content-Type: application/json" \
-d '{
"start": "2025-01-15T14:00:00Z",
"end": "2025-01-15T14:30:00Z",
"timeslot_uuid": "6cb6df60-48d8-11e8-a5e5-263fa1a58213",
"product_uuid": "7fc85970-a2d0-11e2-9cd0-1231430706c1",
"placeholder_id": "a48df610-483c-11f0-b6e3-72fe2304273f",
"email": "interessent@example.com",
"firstname": "Max",
"lastname": "Interessent",
"mobile": "0173 9876543",
"locale": "de"
}'
Sujets connexes
- Aperçu de l'API - Authentification, URL de base, format d'erreur
- Configure Offerings - Créer des ressources et des produits
- Scheduling - Gérer les disponibilités et les rendez-vous
- Intégration du widget - Intégrer le widget BookingJS
